diff --git a/include/wolfprovider/wp_params.h b/include/wolfprovider/wp_params.h index bb534c2d..0ce6d129 100644 --- a/include/wolfprovider/wp_params.h +++ b/include/wolfprovider/wp_params.h @@ -51,7 +51,8 @@ void wp_param_set_mp_buf(OSSL_PARAM* p, const char* key, unsigned char* num, int wp_params_get_digest(const OSSL_PARAM* params, char* name, OSSL_LIB_CTX* libCtx, enum wc_HashType* type, size_t* len); -int wp_params_get_mp(const OSSL_PARAM* params, const char* key, mp_int* mp); +int wp_params_get_mp(const OSSL_PARAM* params, const char* key, mp_int* mp, + int *set); int wp_params_get_octet_string(const OSSL_PARAM* params, const char* key, unsigned char** data, size_t* len, int secure); int wp_params_get_bn_be(const OSSL_PARAM* params, const char* key, @@ -70,7 +71,8 @@ int wp_params_get_int(const OSSL_PARAM* params, const char* key, int* val); int wp_params_get_uint(const OSSL_PARAM* params, const char* key, unsigned int* val, int* set); -int wp_params_set_mp(OSSL_PARAM params[], const char* key, mp_int* mp); +int wp_params_set_mp(OSSL_PARAM params[], const char* key, mp_int* mp, + int allow); int wp_params_set_octet_string_be(OSSL_PARAM params[], const char* key, unsigned char* data, size_t len); diff --git a/src/wp_dh_kmgmt.c b/src/wp_dh_kmgmt.c index 69a43326..cb85fba2 100644 --- a/src/wp_dh_kmgmt.c +++ b/src/wp_dh_kmgmt.c @@ -737,10 +737,12 @@ static int wp_dh_get_params(wp_Dh* dh, OSSL_PARAM params[]) ok = 0; } } - if (ok && (!wp_params_set_mp(params, OSSL_PKEY_PARAM_FFC_P, &dh->key.p))) { + if (ok && (!wp_params_set_mp(params, OSSL_PKEY_PARAM_FFC_P, + &dh->key.p, 1))) { ok = 0; } - if (ok && (!wp_params_set_mp(params, OSSL_PKEY_PARAM_FFC_G, &dh->key.g))) { + if (ok && (!wp_params_set_mp(params, OSSL_PKEY_PARAM_FFC_G, + &dh->key.g, 1))) { ok = 0; } if (ok && (!wp_params_set_octet_string_be(params, OSSL_PKEY_PARAM_PUB_KEY, diff --git a/src/wp_ecc_kmgmt.c b/src/wp_ecc_kmgmt.c index 9ac017ee..579bd699 100644 --- a/src/wp_ecc_kmgmt.c +++ b/src/wp_ecc_kmgmt.c @@ -506,37 +506,33 @@ static const OSSL_PARAM* wp_ecc_settable_params(WOLFPROV_CTX* provCtx) } /** - * Set the public key's X and Y ordinates into ECC key object. + * Set the encoded public key parameter into ECC key object. * * @param [in, out] ecc ECC key object. * @param [in] params Array of parameters and values. + * @param [in] key String to look for. * @return 1 on success. * @return 0 on failure. */ -static int wp_ecc_set_params_x_y(wp_Ecc *ecc, const OSSL_PARAM params[]) +static int wp_ecc_set_params_enc_pub_key(wp_Ecc *ecc, const OSSL_PARAM params[], + const char* key) { int ok = 1; + unsigned char* data = NULL; + size_t len; - if (!wp_params_get_mp(params, OSSL_PKEY_PARAM_EC_PUB_X, - ecc->key.pubkey.x)) { - ok = 0; - } - if (ok && mp_iszero(ecc->key.pubkey.x)) { - ok = 0; - } - if (ok && (!wp_params_get_mp(params, OSSL_PKEY_PARAM_EC_PUB_Y, - ecc->key.pubkey.y))) { - ok = 0; - } - if (ok && mp_iszero(ecc->key.pubkey.x)) { + if (!wp_params_get_octet_string_ptr(params, key, &data, &len)) { ok = 0; } - if (ok) { - ok = (mp_set(ecc->key.pubkey.y, 1) == 0); - } - if (ok) { - ecc->key.type = ECC_PUBLICKEY; - ecc->hasPub = 1; + if (ok && (data != NULL)) { + int rc = wc_ecc_import_x963_ex(data, (word32)len, &ecc->key, + ecc->curveId); + if (rc != 0) { + ok = 0; + } + if (ok) { + ecc->hasPub = 1; + } } WOLFPROV_LEAVE(WP_LOG_PK, __FILE__ ":" WOLFPROV_STRINGIZE(__LINE__), ok); @@ -544,34 +540,43 @@ static int wp_ecc_set_params_x_y(wp_Ecc *ecc, const OSSL_PARAM params[]) } /** - * Set the encoded public key parameter into ECC key object. + * Set the public key values into ECC key object. * * @param [in, out] ecc ECC key object. * @param [in] params Array of parameters and values. - * @param [in] key String to look for. * @return 1 on success. * @return 0 on failure. */ -static int wp_ecc_set_params_enc_pub_key(wp_Ecc *ecc, const OSSL_PARAM params[], - const char* key) +static int wp_ecc_set_params_pub(wp_Ecc *ecc, const OSSL_PARAM params[]) { int ok = 1; - unsigned char* data = NULL; - size_t len; + int set = 0; - if (!wp_params_get_octet_string_ptr(params, key, &data, &len)) { + if (!wp_params_get_mp(params, OSSL_PKEY_PARAM_EC_PUB_X, + ecc->key.pubkey.x, &set)) { ok = 0; } - if (ok && (data != NULL)) { - int rc = wc_ecc_import_x963_ex(data, (word32)len, &ecc->key, - ecc->curveId); - if (rc != 0) { + if (ok && (set == 1)) { + if (mp_iszero(ecc->key.pubkey.x)) { ok = 0; } if (ok) { + ecc->key.type = ECC_PUBLICKEY; ecc->hasPub = 1; } } + if (!wp_params_get_mp(params, OSSL_PKEY_PARAM_EC_PUB_Y, + ecc->key.pubkey.y, NULL)) { + ok = 0; + } + if (wp_ecc_set_params_enc_pub_key(ecc, params, + OSSL_PKEY_PARAM_ENCODED_PUBLIC_KEY) != 1) { + ok = 0; + } + if (wp_ecc_set_params_enc_pub_key(ecc, params, + OSSL_PKEY_PARAM_PUB_KEY) != 1) { + ok = 0; + } WOLFPROV_LEAVE(WP_LOG_PK, __FILE__ ":" WOLFPROV_STRINGIZE(__LINE__), ok); return ok; @@ -591,11 +596,8 @@ static int wp_ecc_set_params(wp_Ecc *ecc, const OSSL_PARAM params[]) const OSSL_PARAM *p; if (params != NULL) { - if (!wp_ecc_set_params_x_y(ecc, params)) { - if (!wp_ecc_set_params_enc_pub_key(ecc, params, - OSSL_PKEY_PARAM_ENCODED_PUBLIC_KEY)) { - ok = 0; - } + if (!wp_ecc_set_params_pub(ecc, params)) { + ok = 0; } if (ok) { p = OSSL_PARAM_locate_const(params, @@ -695,22 +697,61 @@ static int wp_ecc_get_params_enc_pub_key(wp_Ecc* ecc, OSSL_PARAM params[], int rc; word32 outLen = (word32)p->return_size; - if (p->data == NULL) { - outLen = 1 + 2 * ((ecc->bits + 7) / 8); + if (ecc->hasPub == 0) { + ok = 0; } - else { - rc = wc_ecc_export_x963_ex(&ecc->key, p->data, &outLen, 0); - if (rc != 0) { - ok = 0; + if (ok) { + if (p->data == NULL) { + outLen = 1 + 2 * ((ecc->bits + 7) / 8); } + else { + rc = wc_ecc_export_x963_ex(&ecc->key, p->data, &outLen, 0); + if (rc != 0) { + ok = 0; + } + } + p->return_size = outLen; } - p->return_size = outLen; } WOLFPROV_LEAVE(WP_LOG_PK, __FILE__ ":" WOLFPROV_STRINGIZE(__LINE__), ok); return ok; } +/** + * Get the public key into parameters. + * + * @param [in] ecc ECC key object. + * @param [in, out] params Array of parameters and values. + * @return 1 on success. + * @return 0 on failure. + */ +static int wp_ecc_get_params_pub(wp_Ecc* ecc, OSSL_PARAM params[]) +{ + int ok = 1; + + if (!wp_params_set_mp(params, OSSL_PKEY_PARAM_EC_PUB_X, ecc->key.pubkey.x, + (ecc->hasPub == 1))) { + ok = 0; + } + if (!wp_params_set_mp(params, OSSL_PKEY_PARAM_EC_PUB_Y, ecc->key.pubkey.y, + (ecc->hasPub == 1))) { + ok = 0; + } + /* Encoded public key. */ + if (ok && (!wp_ecc_get_params_enc_pub_key(ecc, params, + OSSL_PKEY_PARAM_ENCODED_PUBLIC_KEY))) { + ok = 0; + } + /* Public key. */ + if (ok && (!wp_ecc_get_params_enc_pub_key(ecc, params, + OSSL_PKEY_PARAM_PUB_KEY))) { + ok = 0; + } + + return ok; +} + /** * Get the ECC key parameters. * @@ -767,33 +808,17 @@ static int wp_ecc_get_params(wp_Ecc* ecc, OSSL_PARAM params[]) ok = 0; } } - /* X-ordinate of public key. */ - if (ok && (!wp_params_set_mp(params, OSSL_PKEY_PARAM_EC_PUB_X, - ecc->key.pubkey.x))) { - ok = 0; - } - /* Y-ordinate of public key. */ - if (ok && (!wp_params_set_mp(params, OSSL_PKEY_PARAM_EC_PUB_Y, - ecc->key.pubkey.y))) { - ok = 0; - } - /* Encoded public key. */ - if (ok && (!wp_ecc_get_params_enc_pub_key(ecc, params, - OSSL_PKEY_PARAM_ENCODED_PUBLIC_KEY))) { - ok = 0; - } - /* Public key. */ - if (ok && (!wp_ecc_get_params_enc_pub_key(ecc, params, - OSSL_PKEY_PARAM_PUB_KEY))) { - ok = 0; + /* Public key */ + if (ok) { + ok = wp_ecc_get_params_pub(ecc, params); } if (ok && (!wp_params_set_mp(params, OSSL_PKEY_PARAM_PRIV_KEY, #if (!defined(HAVE_FIPS) || FIPS_VERSION_GE(5,3)) && LIBWOLFSSL_VERSION_HEX >= 0x05006002 - wc_ecc_key_get_priv(&ecc->key) + wc_ecc_key_get_priv(&ecc->key), #else - &(ecc->key.k) + &(ecc->key.k), #endif - ))) { + 1))) { ok = 0; } /* Private key. */ @@ -1041,19 +1066,16 @@ static int wp_ecc_import_keypair(wp_Ecc* ecc, const OSSL_PARAM params[], { int ok = 1; - /* This call sets hasPub field in wp_Ecc. */ - if (!wp_ecc_set_params_x_y(ecc, params)) { - /* Try direct import of encoded public key instead. */ - ok = wp_ecc_set_params_enc_pub_key(ecc, params, - OSSL_PKEY_PARAM_PUB_KEY); + if (wp_ecc_set_params_pub(ecc, params) != 1) { + ok = 0; } if (ok && priv && (!wp_params_get_mp(params, OSSL_PKEY_PARAM_PRIV_KEY, #if (!defined(HAVE_FIPS) || FIPS_VERSION_GE(5,3)) && LIBWOLFSSL_VERSION_HEX >= 0x05006002 - wc_ecc_key_get_priv(&ecc->key) + wc_ecc_key_get_priv(&ecc->key), #else - &(ecc->key.k) + &(ecc->key.k), #endif - ))) { + NULL))) { ok = 0; } if (ok && @@ -2027,13 +2049,21 @@ static int wp_ecc_decode_pki(wp_Ecc* ecc, unsigned char* data, word32 len) #endif if (ok) { ecc->curveId = ecc->key.dp->id; - /* ECC_PRIVATEKEY_ONLY when no public key data. */ - ecc->hasPub = ecc->key.type == ECC_PRIVATEKEY; ecc->hasPriv = 1; /* Needs curveId set. */ if (!wp_ecc_set_bits(ecc)) { ok = 0; } + + /* Keys decoded from pki should always have public key */ + if (ecc->key.type == ECC_PRIVATEKEY_ONLY) { +#ifdef ECC_TIMING_RESISTANT + rc = wc_ecc_make_pub_ex(&ecc->key, NULL, &ecc->rng); +#else + rc = wc_ecc_make_pub_ex(&ecc->key, NULL, NULL); +#endif + } + ecc->hasPub = 1; } WOLFPROV_LEAVE(WP_LOG_PK, __FILE__ ":" WOLFPROV_STRINGIZE(__LINE__), ok); diff --git a/src/wp_params.c b/src/wp_params.c index 3eeaf1eb..59ef2881 100644 --- a/src/wp_params.c +++ b/src/wp_params.c @@ -254,22 +254,34 @@ int wp_params_get_digest(const OSSL_PARAM* params, char* name, * @param [in] params Array of parameters. * @param [in] key String key to look for. * @param [out] mp Multi-precision number. + * @param [out] set Indicates if mp has been set. * @return 1 on success. * @return 0 on failure. */ -int wp_params_get_mp(const OSSL_PARAM* params, const char* key, mp_int* mp) +int wp_params_get_mp(const OSSL_PARAM* params, const char* key, mp_int* mp, + int *set) { int ok = 1; const OSSL_PARAM* p; + if (set != NULL) { + *set = 0; + } + p = OSSL_PARAM_locate_const(params, key); if ((p != NULL) && (p->data_type != OSSL_PARAM_UNSIGNED_INTEGER)) { - ok = 0; - } - if ((p != NULL) && ok && (!wp_mp_read_unsigned_bin_le(mp, p->data, - p->data_size))) { ok = 0; } + if (ok && (p != NULL)) { + if (!wp_mp_read_unsigned_bin_le(mp, p->data, p->data_size)) { + ok = 0; + } + else { + if (set != NULL) { + *set = 1; + } + } + } WOLFPROV_LEAVE(WP_LOG_PROVIDER, __FILE__ ":" WOLFPROV_STRINGIZE(__LINE__), ok); return ok; @@ -577,16 +589,21 @@ int wp_params_get_uint(const OSSL_PARAM* params, const char* key, * @param [in, out] params Array of parameters. * @param [in] key String key to look for. * @param [in] mp Multi-precision number. + * @param [in] allow This mp is allowed to be set. * @return 1 on success. * @return 0 on failure. */ -int wp_params_set_mp(OSSL_PARAM params[], const char* key, mp_int* mp) +int wp_params_set_mp(OSSL_PARAM params[], const char* key, mp_int* mp, + int allow) { int ok = 1; OSSL_PARAM* p; p = OSSL_PARAM_locate(params, key); - if (p != NULL) { + if ((p != NULL) && (allow != 1)) { + ok = 0; + } + if (ok && (p != NULL)) { size_t outLen = mp_unsigned_bin_size(mp); if (p->data != NULL) { if (p->data_size < outLen) { diff --git a/test/test_ecc.c b/test/test_ecc.c index 7e9ff965..cbf6f989 100644 --- a/test/test_ecc.c +++ b/test/test_ecc.c @@ -22,6 +22,7 @@ #include #include +#include #ifdef WP_HAVE_ECC @@ -59,6 +60,17 @@ static const unsigned char ecc_key_der_224[] = { #endif /* WP_HAVE_EC_P224 */ #ifdef WP_HAVE_EC_P256 +/* prime256v1_EC_private_key*/ +static const unsigned char ec_pder[] = { + 0x30, 0x41, 0x02, 0x01, 0x00, 0x30, 0x13, 0x06, 0x07, 0x2A, + 0x86, 0x48, 0xCE, 0x3D, 0x02, 0x01, 0x06, 0x08, 0x2A, 0x86, + 0x48, 0xCE, 0x3D, 0x03, 0x01, 0x07, 0x04, 0x27, 0x30, 0x25, + 0x02, 0x01, 0x01, 0x04, 0x20, 0x8D, 0x06, 0x5C, 0xA7, 0xA8, + 0x0A, 0xA7, 0x61, 0x7B, 0x3A, 0xF7, 0xEF, 0x34, 0x32, 0x0A, + 0x99, 0x31, 0xD5, 0x7F, 0xAE, 0x74, 0x23, 0x8E, 0x3D, 0x0D, + 0x17, 0x48, 0x00, 0x74, 0x7A, 0x93, 0x89 +}; + static const unsigned char ecc_key_der_256[] = { 0x30, 0x77, 0x02, 0x01, 0x01, 0x04, 0x20, 0x45, 0xB6, 0x69, 0x02, 0x73, 0x9C, 0x6C, 0x85, 0xA1, 0x38, 0x5B, 0x72, 0xE8, @@ -74,6 +86,15 @@ static const unsigned char ecc_key_der_256[] = { 0x34, 0x86, 0xE8, 0x20, 0x58, 0x33, 0x0B, 0x80, 0x34, 0x89, 0xD8 }; + +/* Raw P256 group and priv key for EVP_PKEY_fromdata() */ +static const char *ecc_p256_group_str = "prime256v1"; +static const unsigned char ecc_p256_priv[] = { + 0x89, 0x93, 0x7A, 0x74, 0x00, 0x48, 0x17, 0x0D, 0x3D, 0x8E, + 0x23, 0x74, 0xAE, 0x7F, 0xD5, 0x31, 0x99, 0x0A, 0x32, 0x34, + 0xEF, 0xF7, 0x3A, 0x7B, 0x61, 0xA7, 0x0A, 0xA8, 0xA7, 0x5C, + 0x06, 0x8D +}; #endif /* WP_HAVE_EC_P256 */ #ifdef WP_HAVE_EC_P384 @@ -1576,4 +1597,327 @@ int test_ec_load_cert(void* data) } #endif /* WP_HAVE_ECDSA */ +static int test_ec_pubkey_match_ex(EVP_PKEY *pkey1, EVP_PKEY *pkey2, + const char *key) +{ + int err = 0; + size_t len1 = 0; + size_t len2 = 0; + unsigned char *pubkey1 = NULL; + unsigned char *pubkey2 = NULL; + + if (err == 0) { + if (EVP_PKEY_get_octet_string_param(pkey1, + key, NULL, 0, &len1) != 1) { + err = 1; + } + if (len1 <= 0){ + err = 1; + } + } + if (err == 0) { + pubkey1 = OPENSSL_malloc(len1); + err = pubkey1 == NULL; + } + if (err == 0) { + if (EVP_PKEY_get_octet_string_param(pkey1, + key, pubkey1, len1, &len1) != 1) { + err = 1; + } + } + if (err == 0) { + if (EVP_PKEY_get_octet_string_param(pkey2, + key, NULL, 0, &len2) != 1) { + err = 1; + } + if (len2 <= 0){ + err = 1; + } + } + if (err == 0) { + pubkey2 = OPENSSL_malloc(len2); + err = pubkey2 == NULL; + } + if (err == 0) { + if (EVP_PKEY_get_octet_string_param(pkey2, + key, pubkey2, len2, &len2) != 1) { + err = 1; + } + if (len1 != len2) { + err = 1; + } + } + if (err == 0) { + err = memcmp(pubkey1, pubkey2, len1) != 0; + if (err != 0) { + PRINT_ERR_MSG("ECC public key values do not match!"); + } + } + + OPENSSL_free(pubkey1); + OPENSSL_free(pubkey2); + return err; +} + +static int test_ec_pubkey_match(EVP_PKEY *pkey1, EVP_PKEY *pkey2) { + int err = 0; + + err = test_ec_pubkey_match_ex(pkey1, pkey2, OSSL_PKEY_PARAM_PUB_KEY); + if (err == 0) { + err = test_ec_pubkey_match_ex(pkey1, pkey2, + OSSL_PKEY_PARAM_ENCODED_PUBLIC_KEY); + } + + return err; +} + +static int test_ec_decode1(void) +{ + int err = 0; + EVP_PKEY_CTX *ctx = NULL; + PKCS8_PRIV_KEY_INFO* p8inf = NULL; + const unsigned char *p = NULL; + int len = 0; + EVP_PKEY* pkey1 = NULL; + EC_KEY* eckey1 = NULL; + const EC_GROUP* grp1 = NULL; + const BIGNUM* pk1 = NULL; + EVP_PKEY* pkey2 = NULL; + EC_KEY* eckey2 = NULL; + const EC_GROUP* grp2 = NULL; + const BIGNUM* pk2 = NULL; + + p = &ec_pder[0]; + len = sizeof(ec_pder); + p8inf = d2i_PKCS8_PRIV_KEY_INFO(NULL, (const unsigned char **)&p, len); + err = p8inf == NULL; + + if (err == 0) { + PRINT_MSG("Decode with OpenSSL and Wolfprovider"); + pkey1 = EVP_PKCS82PKEY_ex(p8inf, osslLibCtx, NULL); + pkey2 = EVP_PKCS82PKEY_ex(p8inf, wpLibCtx, NULL); + PKCS8_PRIV_KEY_INFO_free(p8inf); + err = (pkey1 == NULL || pkey2 == NULL); + } + + /* Pull an old style EC_KEY structure from the decoded pkey */ + if (err == 0) { + eckey1 = EVP_PKEY_get1_EC_KEY(pkey1); + eckey2 = EVP_PKEY_get1_EC_KEY(pkey2); + err = (eckey1 == NULL || eckey2 == NULL); + } + if (err == 0) { + grp1 = EC_KEY_get0_group(eckey1); + err = grp1 == NULL; + } + if (err == 0) { + pk1 = EC_KEY_get0_private_key(eckey1); + err = pk1 == NULL; + } + if (err == 0) { + grp2 = EC_KEY_get0_group(eckey2); + err = grp2 == NULL; + } + if (err == 0) { + pk2 = EC_KEY_get0_private_key(eckey2); + err = pk2 == NULL; + } + + /* Ensure we filled out the structure the same as openssl */ + if (err == 0) { + err = EC_GROUP_cmp(grp1, grp2, NULL) != 0; + } + if (err == 0) { + err = BN_cmp(pk1, pk2) != 0; + } + + EC_KEY_free(eckey1); + EC_KEY_free(eckey2); + EVP_PKEY_free(pkey1); + EVP_PKEY_free(pkey2); + EVP_PKEY_CTX_free(ctx); + + return err; +} + +static int test_ec_decode2(void) +{ + int err = 0; + EVP_PKEY_CTX *ctx = NULL; + PKCS8_PRIV_KEY_INFO* p8inf = NULL; + const unsigned char *p = NULL; + EVP_PKEY* pkey1 = NULL; + EVP_PKEY* pkey2 = NULL; + BIGNUM* x1 = NULL; + BIGNUM* x2 = NULL; + BIGNUM* y1 = NULL; + BIGNUM* y2 = NULL; + int len = 0; + + p = &ec_pder[0]; + len = sizeof(ec_pder); + p8inf = d2i_PKCS8_PRIV_KEY_INFO(NULL, (const unsigned char **)&p, len); + err = p8inf == NULL; + + if (err == 0) { + PRINT_MSG("Decode with OpenSSL and Wolfprovider"); + pkey1 = EVP_PKCS82PKEY_ex(p8inf, osslLibCtx, NULL); + pkey2 = EVP_PKCS82PKEY_ex(p8inf, wpLibCtx, NULL); + PKCS8_PRIV_KEY_INFO_free(p8inf); + err = (pkey1 == NULL || pkey2 == NULL); + } + + /* For decoded keys, get bn params should work */ + if (err == 0) { + err = EVP_PKEY_get_bn_param(pkey1, OSSL_PKEY_PARAM_EC_PUB_X, &x1) != 1; + } + if (err == 0) { + err = EVP_PKEY_get_bn_param(pkey2, OSSL_PKEY_PARAM_EC_PUB_X, &x2) != 1; + } + if (err == 0) { + err = BN_cmp(x1, x2) != 0; + } + if (err == 0) { + err = EVP_PKEY_get_bn_param(pkey1, OSSL_PKEY_PARAM_EC_PUB_Y, &y1) != 1; + } + if (err == 0) { + err = EVP_PKEY_get_bn_param(pkey2, OSSL_PKEY_PARAM_EC_PUB_Y, &y2) != 1; + } + if (err == 0) { + err = BN_cmp(y1, y2) != 0; + } + + /* Get public key should work for decoded keys */ + err = test_ec_pubkey_match(pkey1, pkey2); + + BN_free(x1); + BN_free(x2); + BN_free(y1); + BN_free(y2); + EVP_PKEY_free(pkey1); + EVP_PKEY_free(pkey2); + EVP_PKEY_CTX_free(ctx); + + return err; +} + +int test_ec_decode(void* data) +{ + int err = 0; + (void)data; + + err = test_ec_decode1(); + if (err == 0) { + err = test_ec_decode2(); + } + + return err; +} + +int test_ec_import(void* data) +{ + int err = 0; + int len = 0; + EVP_PKEY_CTX *ctx1 = NULL; + EVP_PKEY_CTX *ctx2 = NULL; + EVP_PKEY* pkey1 = NULL; + EVP_PKEY* pkey2 = NULL; + BIGNUM* x1 = NULL; + BIGNUM* x2 = NULL; + BIGNUM* y1 = NULL; + BIGNUM* y2 = NULL; + OSSL_PARAM *params = NULL; + OSSL_PARAM_BLD *bld = NULL; + BIGNUM* priv = NULL; + + (void)data; + + /* Hand construct ECC private only key simulating bind9 flow */ + err = (bld = OSSL_PARAM_BLD_new()) == NULL; + if (err == 0) { + err = OSSL_PARAM_BLD_push_utf8_string(bld, OSSL_PKEY_PARAM_GROUP_NAME, + ecc_p256_group_str, 0) != 1; + } + if (err == 0) { + err = (priv = BN_bin2bn(ecc_p256_priv, + sizeof(ecc_p256_priv), NULL)) == NULL; + } + if (err == 0) { + err = OSSL_PARAM_BLD_push_BN(bld, OSSL_PKEY_PARAM_PRIV_KEY, priv) != 1; + } + if (err == 0) { + err = (params = OSSL_PARAM_BLD_to_param(bld)) == NULL; + } + /* Create openssl and wolfprovider backed pkey */ + if (err == 0) { + err = (ctx1 = EVP_PKEY_CTX_new_from_name(osslLibCtx, "EC", NULL)) == NULL; + } + if (err == 0) { + err = EVP_PKEY_fromdata_init(ctx1) != 1; + } + if (err == 0) { + err = EVP_PKEY_fromdata(ctx1, &pkey1, EVP_PKEY_KEYPAIR, params) != 1; + } + if (err == 0) { + err = (ctx2 = EVP_PKEY_CTX_new_from_name(wpLibCtx, "EC", NULL)) == NULL; + } + if (err == 0) { + err = EVP_PKEY_fromdata_init(ctx2) != 1; + } + if (err == 0) { + err = EVP_PKEY_fromdata(ctx2, &pkey2, EVP_PKEY_KEYPAIR, params) != 1; + } + + /* For imported private only keys, get bn params should fail */ + if (err == 0) { + err = EVP_PKEY_get_bn_param(pkey1, OSSL_PKEY_PARAM_EC_PUB_X, &x1) == 1; + } + if (err == 0) { + err = EVP_PKEY_get_bn_param(pkey2, OSSL_PKEY_PARAM_EC_PUB_X, &x2) == 1; + } + if (err == 0) { + err = EVP_PKEY_get_bn_param(pkey1, OSSL_PKEY_PARAM_EC_PUB_Y, &y1) == 1; + } + if (err == 0) { + err = EVP_PKEY_get_bn_param(pkey2, OSSL_PKEY_PARAM_EC_PUB_Y, &y2) == 1; + } + + /* Attempts to get the public key len should fail */ + if (err == 0) { + if (EVP_PKEY_get_octet_string_param(pkey1, + OSSL_PKEY_PARAM_PUB_KEY, NULL, 0, (size_t *)&len) != 0) { + err = 1; + } + } + if (err == 0) { + if (EVP_PKEY_get_octet_string_param(pkey2, + OSSL_PKEY_PARAM_PUB_KEY, NULL, 0, (size_t *)&len) != 0) { + err = 1; + } + } + if (err == 0) { + if (EVP_PKEY_get_octet_string_param(pkey1, + OSSL_PKEY_PARAM_ENCODED_PUBLIC_KEY, NULL, 0, (size_t *)&len) != 0) { + err = 1; + } + } + if (err == 0) { + if (EVP_PKEY_get_octet_string_param(pkey2, + OSSL_PKEY_PARAM_ENCODED_PUBLIC_KEY, NULL, 0, (size_t *)&len) != 0) { + err = 1; + } + } + + EVP_PKEY_free(pkey1); + EVP_PKEY_free(pkey2); + EVP_PKEY_CTX_free(ctx1); + EVP_PKEY_CTX_free(ctx2); + OSSL_PARAM_free(params); + OSSL_PARAM_BLD_free(bld); + BN_clear_free(priv); + + return err; +} + + #endif /* WP_HAVE_ECC */ diff --git a/test/unit.c b/test/unit.c index b2b710cb..3adedbe4 100644 --- a/test/unit.c +++ b/test/unit.c @@ -209,6 +209,8 @@ TEST_CASE test_case[] = { TEST_DECL(test_ecdsa_p256_pkey, NULL), TEST_DECL(test_ecdsa_p256, NULL), #endif + TEST_DECL(test_ec_decode, NULL), + TEST_DECL(test_ec_import, NULL), #endif #ifdef WP_HAVE_EC_P384 #ifdef WP_HAVE_ECKEYGEN diff --git a/test/unit.h b/test/unit.h index cf33f4fa..53d48be9 100644 --- a/test/unit.h +++ b/test/unit.h @@ -366,6 +366,9 @@ int test_ec_load_key(void* data); int test_ec_load_cert(void* data); #endif /* WP_HAVE_ECDSA */ +int test_ec_decode(void* data); +int test_ec_import(void* data); + #endif /* WP_HAVE_ECC */ #ifdef WP_HAVE_PBE