diff --git a/src/wp_ecc_kmgmt.c b/src/wp_ecc_kmgmt.c index 153e415e..1a3f13ce 100644 --- a/src/wp_ecc_kmgmt.c +++ b/src/wp_ecc_kmgmt.c @@ -1995,6 +1995,28 @@ static int wp_ecc_decode_params(wp_Ecc* ecc, unsigned char* data, word32 len) return ok; } +static int wp_ecc_decode_x963_pub(wp_Ecc* ecc, unsigned char* data, word32 len) +{ + int ok = 1; + int rc; + + rc = wc_ecc_import_x963((const byte *)data, len, &ecc->key); + if (rc != 0) { + ok = 0; + } + if (ok) { + ecc->curveId = ecc->key.dp->id; + ecc->hasPub = 1; + /* Needs curveId set. */ + if (!wp_ecc_set_bits(ecc)) { + ok = 0; + } + } + + WOLFPROV_LEAVE(WP_LOG_PK, __FILE__ ":" WOLFPROV_STRINGIZE(__LINE__), ok); + return ok; +} + /** * Decode the SubjectPublicInfo DER encoded ECC key into the ECC key object. * @@ -2160,6 +2182,12 @@ static int wp_ecc_decode(wp_EccEncDecCtx* ctx, OSSL_CORE_BIO *cBio, decoded = 0; } } + else if (selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) { + if (!wp_ecc_decode_x963_pub(ecc, data, len)) { + ok = 0; + decoded = 0; + } + } else { if (!wp_ecc_decode_params(ecc, data, len)) { ok = 0; @@ -2253,6 +2281,61 @@ static int wp_ecc_encode_params(const wp_Ecc *ecc, unsigned char* keyData, return ok; } +/** + * Get the public key encoding size. + * + * @param [in] ecc ECC key object. + * @param [out] keyLen Length of encoding in bytes. + * @return 1 on success. + * @return 0 on failure. + */ +static int wp_ecc_encode_pub_size(const wp_Ecc *ecc, size_t* keyLen) +{ + int ok = 1; + int rc; + word32 len; + + rc = wc_ecc_export_x963_ex((ecc_key*)&ecc->key, NULL, &len, 0); + if (rc != LENGTH_ONLY_E) { + ok = 0; + } + if (ok) { + *keyLen = len; + } + + WOLFPROV_LEAVE(WP_LOG_PK, __FILE__ ":" WOLFPROV_STRINGIZE(__LINE__), ok); + return ok; +} + +/** + * Encode the ECC public key. + * + * @param [in] ecc ECC key object. + * @param [out] keyData Buffer to hold encoded data. + * @param [in, out] keyLen On in, length of buffer in bytes. + * On out, length of encoding in bytes. + * @return 1 on success. + * @return 0 on failure. + */ +static int wp_ecc_encode_pub(const wp_Ecc *ecc, unsigned char* keyData, + size_t* keyLen) +{ + int ok = 1; + int rc; + word32 len = (word32)*keyLen; + + rc = wc_ecc_export_x963_ex((ecc_key*)&ecc->key, keyData, &len, 0); + if (rc != 0) { + ok = 0; + } + if (ok) { + *keyLen = len; + } + + WOLFPROV_LEAVE(WP_LOG_PK, __FILE__ ":" WOLFPROV_STRINGIZE(__LINE__), ok); + return ok; +} + /** * Get the PKCS#8 encoding size for the key. * @@ -2548,6 +2631,11 @@ static int wp_ecc_encode(wp_EccEncDecCtx* ctx, OSSL_CORE_BIO *cBio, ok = 0; } } + else if (selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) { + if (!wp_ecc_encode_pub_size(key, &derLen)) { + ok = 0; + } + } else if (selection & OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS) { if (!wp_ecc_encode_params_size(key, &derLen)) { ok = 0; @@ -2591,6 +2679,12 @@ static int wp_ecc_encode(wp_EccEncDecCtx* ctx, OSSL_CORE_BIO *cBio, ok = 0; } } + else if (selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) { + pemType = PUBLICKEY_TYPE; + if (!wp_ecc_encode_pub(key, derData, &derLen)) { + ok = 0; + } + } else if (selection & OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS) { pemType = DH_PARAM_TYPE; if (!wp_ecc_encode_params(key, derData, &derLen)) {