@@ -131,6 +131,31 @@ struct OpenSSLBufferDeleter {
131131};
132132using OpenSSLBufferPointer =
133133 std::unique_ptr<unsigned char , OpenSSLBufferDeleter>;
134+
135+ struct RsaOtherPrimeParamNames {
136+ const char * factor;
137+ const char * exponent;
138+ const char * coefficient;
139+ };
140+
141+ #define RSA_OTHER_PRIME_PARAM_NAMES (prime, coefficient ) \
142+ { \
143+ OSSL_PKEY_PARAM_RSA_FACTOR #prime, OSSL_PKEY_PARAM_RSA_EXPONENT #prime, \
144+ OSSL_PKEY_PARAM_RSA_COEFFICIENT #coefficient \
145+ }
146+
147+ constexpr std::array<RsaOtherPrimeParamNames, 8 > kRsaOtherPrimeParamNames = {{
148+ RSA_OTHER_PRIME_PARAM_NAMES (3 , 2 ),
149+ RSA_OTHER_PRIME_PARAM_NAMES (4 , 3 ),
150+ RSA_OTHER_PRIME_PARAM_NAMES (5 , 4 ),
151+ RSA_OTHER_PRIME_PARAM_NAMES (6 , 5 ),
152+ RSA_OTHER_PRIME_PARAM_NAMES (7 , 6 ),
153+ RSA_OTHER_PRIME_PARAM_NAMES (8 , 7 ),
154+ RSA_OTHER_PRIME_PARAM_NAMES (9 , 8 ),
155+ RSA_OTHER_PRIME_PARAM_NAMES (10 , 9 ),
156+ }};
157+
158+ #undef RSA_OTHER_PRIME_PARAM_NAMES
134159#endif
135160
136161static constexpr int kX509NameFlagsRFC2253WithinUtf8JSON =
@@ -3082,6 +3107,19 @@ EVPKeyPointer EVPKeyPointer::NewRSA(const Rsa& rsa) {
30823107 bld.get (), OSSL_PKEY_PARAM_RSA_COEFFICIENT1 , private_key.qi ) != 1 ) {
30833108 return {};
30843109 }
3110+
3111+ const auto other_prime_infos = rsa.getOtherPrimeInfos ();
3112+ if (other_prime_infos.size () > kRsaOtherPrimeParamNames .size ()) return {};
3113+ for (size_t i = 0 ; i < other_prime_infos.size (); i++) {
3114+ const auto & info = other_prime_infos[i];
3115+ const auto & names = kRsaOtherPrimeParamNames [i];
3116+ if (info.r == nullptr || info.d == nullptr || info.t == nullptr ||
3117+ OSSL_PARAM_BLD_push_BN (bld.get (), names.factor , info.r ) != 1 ||
3118+ OSSL_PARAM_BLD_push_BN (bld.get (), names.exponent , info.d ) != 1 ||
3119+ OSSL_PARAM_BLD_push_BN (bld.get (), names.coefficient , info.t ) != 1 ) {
3120+ return {};
3121+ }
3122+ }
30853123 selection = EVP_PKEY_KEYPAIR ;
30863124 }
30873125
@@ -6132,6 +6170,11 @@ DataPointer CipherImpl(const EVPKeyPointer& key,
61326170}
61336171} // namespace
61346172
6173+ Rsa::OtherPrimeInfoPointer::OtherPrimeInfoPointer (BignumPointer&& r,
6174+ BignumPointer&& d,
6175+ BignumPointer&& t)
6176+ : r (r.release ()), d (d.release ()), t (t.release ()) {}
6177+
61356178#if NCRYPTO_USE_OPENSSL3_PROVIDER
61366179namespace {
61376180int DigestAlgorithmIdentifierToNid (const unsigned char * data, size_t size) {
@@ -6360,6 +6403,19 @@ Rsa::Rsa(const EVP_PKEY* pkey) : Rsa() {
63606403 return ;
63616404 }
63626405
6406+ for (const auto & names : kRsaOtherPrimeParamNames ) {
6407+ OtherPrimeInfoPointer info;
6408+ if (!GetOptionalPKeyBnParam (pkey, names.factor , &info.r ) ||
6409+ !GetOptionalPKeyBnParam (pkey, names.exponent , &info.d ) ||
6410+ !GetOptionalPKeyBnParam (pkey, names.coefficient , &info.t )) {
6411+ return ;
6412+ }
6413+
6414+ if (!info.r && !info.d && !info.t ) break ;
6415+ if (!info.r || !info.d || !info.t ) return ;
6416+ other_prime_infos_.push_back (std::move (info));
6417+ }
6418+
63636419 if (type == EVP_PKEY_RSA_PSS ) {
63646420 MarkPopErrorOnReturn pop_errors;
63656421 PssParams params;
@@ -6398,6 +6454,35 @@ const Rsa::PrivateKey Rsa::getPrivateKey() const {
63986454#endif
63996455}
64006456
6457+ const Rsa::OtherPrimeInfos Rsa::getOtherPrimeInfos () const {
6458+ OtherPrimeInfos infos;
6459+ #if NCRYPTO_USE_OPENSSL3_PROVIDER
6460+ infos.reserve (other_prime_infos_.size ());
6461+ for (const auto & info : other_prime_infos_) {
6462+ infos.push_back ({info.r .get (), info.d .get (), info.t .get ()});
6463+ }
6464+ #elif NCRYPTO_USE_LEGACY_OPENSSL
6465+ if (rsa_ == nullptr ) return infos;
6466+ const int count = RSA_get_multi_prime_extra_count (rsa_);
6467+ if (count <= 0 ) return infos;
6468+
6469+ std::vector<const BIGNUM *> factors (count);
6470+ std::vector<const BIGNUM *> exponents (count);
6471+ std::vector<const BIGNUM *> coefficients (count);
6472+ if (RSA_get0_multi_prime_factors (rsa_, factors.data ()) != 1 ||
6473+ RSA_get0_multi_prime_crt_params (
6474+ rsa_, exponents.data (), coefficients.data ()) != 1 ) {
6475+ return {};
6476+ }
6477+
6478+ infos.reserve (count);
6479+ for (int i = 0 ; i < count; i++) {
6480+ infos.push_back ({factors[i], exponents[i], coefficients[i]});
6481+ }
6482+ #endif
6483+ return infos;
6484+ }
6485+
64016486const std::optional<Rsa::PssParams> Rsa::getPssParams () const {
64026487#if NCRYPTO_USE_OPENSSL3_PROVIDER
64036488 return pss_params_;
@@ -6499,15 +6584,20 @@ bool Rsa::setPrivateKey(BignumPointer&& d,
64996584 BignumPointer&& p,
65006585 BignumPointer&& dp,
65016586 BignumPointer&& dq,
6502- BignumPointer&& qi) {
6587+ BignumPointer&& qi,
6588+ OtherPrimeInfoPointers&& other_prime_infos) {
65036589#if NCRYPTO_USE_OPENSSL3_PROVIDER
65046590 if (!d || !q || !p || !dp || !dq || !qi) return false ;
6591+ for (const auto & info : other_prime_infos) {
6592+ if (!info.r || !info.d || !info.t ) return false ;
6593+ }
65056594 d_.reset (d.release ());
65066595 q_.reset (q.release ());
65076596 p_.reset (p.release ());
65086597 dp_.reset (dp.release ());
65096598 dq_.reset (dq.release ());
65106599 qi_.reset (qi.release ());
6600+ other_prime_infos_ = std::move (other_prime_infos);
65116601 rsa_ = n_ != nullptr && e_ != nullptr ;
65126602 return rsa_;
65136603#else
@@ -6529,6 +6619,37 @@ bool Rsa::setPrivateKey(BignumPointer&& d,
65296619 dp.release ();
65306620 dq.release ();
65316621 qi.release ();
6622+
6623+ #if NCRYPTO_USE_LEGACY_OPENSSL
6624+ if (!other_prime_infos.empty ()) {
6625+ std::vector<BIGNUM *> factors;
6626+ std::vector<BIGNUM *> exponents;
6627+ std::vector<BIGNUM *> coefficients;
6628+ factors.reserve (other_prime_infos.size ());
6629+ exponents.reserve (other_prime_infos.size ());
6630+ coefficients.reserve (other_prime_infos.size ());
6631+ for (const auto & info : other_prime_infos) {
6632+ if (!info.r || !info.d || !info.t ) return false ;
6633+ factors.push_back (info.r .get ());
6634+ exponents.push_back (info.d .get ());
6635+ coefficients.push_back (info.t .get ());
6636+ }
6637+ if (RSA_set0_multi_prime_params (const_cast <RSA *>(rsa_),
6638+ factors.data (),
6639+ exponents.data (),
6640+ coefficients.data (),
6641+ static_cast <int >(factors.size ())) != 1 ) {
6642+ return false ;
6643+ }
6644+ for (auto & info : other_prime_infos) {
6645+ info.r .release ();
6646+ info.d .release ();
6647+ info.t .release ();
6648+ }
6649+ }
6650+ #else
6651+ if (!other_prime_infos.empty ()) return false ;
6652+ #endif
65326653 return true ;
65336654#endif
65346655}
0 commit comments