@@ -6381,10 +6381,15 @@ bool EVPKeyCtxPointer::setDsaParameters(uint32_t bits,
63816381}
63826382
63836383bool EVPKeyCtxPointer::setEcParameters (int curve, int encoding) {
6384- if (!ctx_) return false ;
6384+ return setEcParameters (OBJ_nid2sn (curve), encoding);
6385+ }
6386+
6387+ bool EVPKeyCtxPointer::setEcParameters (const char * group_name, int encoding) {
6388+ if (!ctx_ || group_name == nullptr ) return false ;
6389+ const int curve = Ec::GetCurveIdFromName (group_name);
63856390#if NCRYPTO_USE_OPENSSL3_PROVIDER
6386- const char * group_name = OBJ_nid2sn (curve);
6387- if (group_name == nullptr ) return false ;
6391+ // Keep the historical aliases while allowing names known only to providers.
6392+ if (curve != NID_undef) group_name = OBJ_nid2sn (curve) ;
63886393
63896394 const char * encoding_name = nullptr ;
63906395 switch (encoding) {
@@ -6406,7 +6411,8 @@ bool EVPKeyCtxPointer::setEcParameters(int curve, int encoding) {
64066411 };
64076412 return EVP_PKEY_CTX_set_params (ctx_.get (), params) == 1 ;
64086413#else
6409- return EVP_PKEY_CTX_set_ec_paramgen_curve_nid (ctx_.get (), curve) == 1 &&
6414+ return curve != NID_undef &&
6415+ EVP_PKEY_CTX_set_ec_paramgen_curve_nid (ctx_.get (), curve) == 1 &&
64106416 EVP_PKEY_CTX_set_ec_param_enc (ctx_.get (), encoding) == 1 ;
64116417#endif
64126418}
@@ -7491,6 +7497,57 @@ int Ec::GetCurveId(const EVPKeyPointer& key) {
74917497#endif
74927498}
74937499
7500+ std::optional<std::string> Ec::GetCurveName (const EVPKeyPointer& key) {
7501+ if (!key) return std::nullopt ;
7502+ #if NCRYPTO_USE_OPENSSL3_PROVIDER
7503+ size_t length = 0 ;
7504+ if (EVP_PKEY_get_utf8_string_param (
7505+ key.get (), OSSL_PKEY_PARAM_GROUP_NAME , nullptr , 0 , &length) != 1 ) {
7506+ return std::nullopt ;
7507+ }
7508+ std::string name (length, ' \0 ' );
7509+ if (EVP_PKEY_get_utf8_string_param (key.get (),
7510+ OSSL_PKEY_PARAM_GROUP_NAME ,
7511+ name.data (),
7512+ name.size () + 1 ,
7513+ &length) != 1 ) {
7514+ return std::nullopt ;
7515+ }
7516+ name.resize (length);
7517+ // Preserve the public short names for the curves OpenSSL already knows.
7518+ const int nid = GetCurveIdFromName (name.c_str ());
7519+ return nid == NID_undef ? name : std::string (OBJ_nid2sn (nid));
7520+ #else
7521+ const int nid = GetCurveId (key);
7522+ if (nid == NID_undef) return std::nullopt ;
7523+ return std::string (OBJ_nid2sn (nid));
7524+ #endif
7525+ }
7526+
7527+ #if NCRYPTO_USE_OPENSSL3_PROVIDER
7528+ namespace {
7529+ bool IsAvailableEcGroup (const char * name) {
7530+ MarkPopErrorOnReturn mark;
7531+ auto ctx = EVPKeyCtxPointer::NewFromAlgorithm (KeyAlgorithm::EC );
7532+ return ctx.initForParamgen () &&
7533+ ctx.setEcParameters (name, OPENSSL_EC_NAMED_CURVE ) && ctx.paramgen ();
7534+ }
7535+ } // namespace
7536+ #endif
7537+
7538+ bool Ec::CheckCurveName (const char * name) {
7539+ if (name == nullptr ) return false ;
7540+ if (GetCurveIdFromName (name) != NID_undef) return true ;
7541+ #if NCRYPTO_USE_OPENSSL3_PROVIDER
7542+ // Keep invalid names a synchronous argument error. Generation contexts can
7543+ // defer rejecting a group until parameter generation. Use the same parameter
7544+ // generation path as key generation without requiring parameter import.
7545+ return IsAvailableEcGroup (name);
7546+ #else
7547+ return false ;
7548+ #endif
7549+ }
7550+
74947551int Ec::GetCurveIdFromName (const char * name) {
74957552 int nid = EC_curve_nist2nid (name);
74967553 if (nid == NID_undef) {
@@ -7513,8 +7570,12 @@ bool Ec::GetCurves(Ec::GetCurveCallback callback) {
75137570 if (EC_get_builtin_curves (curves.data (), count) != count) {
75147571 return false ;
75157572 }
7516- for (auto curve : curves) {
7517- if (!callback (OBJ_nid2sn (curve.nid ))) return false ;
7573+ for (const auto & curve : curves) {
7574+ const char * name = OBJ_nid2sn (curve.nid );
7575+ #if NCRYPTO_USE_OPENSSL3_PROVIDER
7576+ if (!IsAvailableEcGroup (name)) continue ;
7577+ #endif
7578+ if (!callback (name)) return false ;
75187579 }
75197580 return true ;
75207581}
0 commit comments