diff --git a/src/pk.c b/src/pk.c index 5292314dd..aa172b2a4 100644 --- a/src/pk.c +++ b/src/pk.c @@ -32,6 +32,12 @@ #ifdef HAVE_ECC #include + #ifdef HAVE_SELFTEST + /* point compression types. */ + #define ECC_POINT_COMP_EVEN 0x02 + #define ECC_POINT_COMP_ODD 0x03 + #define ECC_POINT_UNCOMP 0x04 + #endif #endif #ifndef WOLFSSL_HAVE_ECC_KEY_GET_PRIV /* FIPS build has replaced ecc.h. */ @@ -9870,7 +9876,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 @@ -9983,7 +9988,100 @@ 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[MAX_ECC_BYTES * 2 + 1]; + + /* for compressed mode */ + int key_sz; + byte *octGx = (byte *)strGx; /* octGx[MAX_ECC_BYTES] */ + + 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 = 1; + } + + key_sz = (wolfSSL_EC_GROUP_get_degree(group) + 7) / 8; + if (hex[0] == '0' && hex[1] == '4') { /* uncompressed mode */ + str_sz = key_sz * 2; + + XMEMSET(strGx, 0x0, str_sz + 1); + XMEMCPY(strGx, hex + 2, str_sz); + + if (wolfSSL_BN_hex2bn(&Gx, strGx) == 0) + goto err; + + if (wolfSSL_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')) { + size_t sz = XSTRLEN(hex + 2) / 2; + /* compressed mode */ + octGx[0] = ECC_POINT_COMP_ODD; + if (hex_to_bytes(hex + 2, octGx + 1, sz) != sz) { + goto err; + } + if (wolfSSL_ECPoint_d2i(octGx, key_sz + 1, group, p) + != WOLFSSL_SUCCESS) { + goto err; + } + } + else + goto err; + + wolfSSL_BN_free(Gx); + wolfSSL_BN_free(Gy); + return p; + +err: + 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 ecf9b36a4..5b51020ec 100644 --- a/tests/api.c +++ b/tests/api.c @@ -61767,6 +61767,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; @@ -61784,6 +61785,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; @@ -61792,10 +61801,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, @@ -61813,8 +61818,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, @@ -62039,7 +62042,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)); @@ -62056,13 +62058,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 fcfcb1e42..da988c6a9 100644 --- a/wolfssl/openssl/ec.h +++ b/wolfssl/openssl/ec.h @@ -318,12 +318,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); WOLFSSL_API const WOLFSSL_EC_KEY_METHOD *wolfSSL_EC_KEY_OpenSSL(void); WOLFSSL_API WOLFSSL_EC_KEY_METHOD *wolfSSL_EC_KEY_METHOD_new( @@ -423,9 +425,8 @@ typedef WOLFSSL_EC_KEY_METHOD EC_KEY_METHOD; #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