@@ -93,7 +93,11 @@ const EVP_MD* GetDigestCtxMd(const EVP_MD_CTX* ctx) {
9393}
9494
9595#if NCRYPTO_USE_OPENSSL3_PROVIDER
96+ using ASN1StringPointer = DeleteFnPtr<ASN1_STRING , ASN1_STRING_free>;
9697using OSSLParamBldPointer = DeleteFnPtr<OSSL_PARAM_BLD , OSSL_PARAM_BLD_free>;
98+ using RsaPssParamsPointer = DeleteFnPtr<RSA_PSS_PARAMS , RSA_PSS_PARAMS_free>;
99+ using X509AlgorPointer = DeleteFnPtr<X509_ALGOR , X509_ALGOR_free>;
100+ using X509PubkeyPointer = DeleteFnPtr<X509_PUBKEY , X509_PUBKEY_free>;
97101struct OSSLParamDeleter {
98102 void operator ()(OSSL_PARAM * params) const {
99103 if (params == nullptr ) return ;
@@ -5702,13 +5706,74 @@ bool ReadRsaPssParams(const EVP_PKEY* pkey, Rsa::PssParams* params) {
57025706
57035707 return true ;
57045708}
5709+
5710+ bool SetRsaPssHashAlgorithm (X509_ALGOR ** out, const Digest& digest) {
5711+ if (EVP_MD_is_a (digest.get (), " SHA1" )) return true ;
5712+
5713+ X509AlgorPointer algorithm (X509_ALGOR_new ());
5714+ if (!algorithm) return false ;
5715+ X509_ALGOR_set_md (algorithm.get (), digest.get ());
5716+ *out = algorithm.release ();
5717+ return true ;
5718+ }
5719+
5720+ bool SetRsaPssMaskGenAlgorithm (X509_ALGOR ** out, const Digest& digest) {
5721+ if (EVP_MD_is_a (digest.get (), " SHA1" )) return true ;
5722+
5723+ X509AlgorPointer hash_algorithm (X509_ALGOR_new ());
5724+ if (!hash_algorithm) return false ;
5725+ X509_ALGOR_set_md (hash_algorithm.get (), digest.get ());
5726+
5727+ ASN1StringPointer hash_algorithm_der (ASN1_item_pack (
5728+ hash_algorithm.get (), ASN1_ITEM_rptr (X509_ALGOR ), nullptr ));
5729+ if (!hash_algorithm_der) return false ;
5730+
5731+ X509AlgorPointer algorithm (X509_ALGOR_new ());
5732+ if (!algorithm || X509_ALGOR_set0 (algorithm.get (),
5733+ OBJ_nid2obj (NID_mgf1),
5734+ V_ASN1_SEQUENCE ,
5735+ hash_algorithm_der.get ()) != 1 ) {
5736+ return false ;
5737+ }
5738+ hash_algorithm_der.release ();
5739+ *out = algorithm.release ();
5740+ return true ;
5741+ }
5742+
5743+ ASN1StringPointer EncodeRsaPssParams (const Rsa::PssParams& params) {
5744+ const Digest digest = Digest::FromName (params.digest .data ());
5745+ if (!digest) return {};
5746+
5747+ const Digest mgf1_digest = params.mgf1_digest
5748+ ? Digest::FromName (params.mgf1_digest ->data ())
5749+ : digest;
5750+ if (!mgf1_digest) return {};
5751+
5752+ RsaPssParamsPointer pss (RSA_PSS_PARAMS_new ());
5753+ if (!pss || !SetRsaPssHashAlgorithm (&pss->hashAlgorithm , digest) ||
5754+ !SetRsaPssMaskGenAlgorithm (&pss->maskGenAlgorithm , mgf1_digest)) {
5755+ return {};
5756+ }
5757+
5758+ if (params.salt_length != 20 ) {
5759+ pss->saltLength = ASN1_INTEGER_new ();
5760+ if (pss->saltLength == nullptr ||
5761+ ASN1_INTEGER_set_int64 (pss->saltLength , params.salt_length ) != 1 ) {
5762+ return {};
5763+ }
5764+ }
5765+
5766+ return ASN1StringPointer (
5767+ ASN1_item_pack (pss.get (), ASN1_ITEM_rptr (RSA_PSS_PARAMS ), nullptr ));
5768+ }
57055769} // namespace
57065770
57075771Rsa::Rsa () : rsa_ (false ) {}
57085772
57095773Rsa::Rsa (const EVP_PKEY * pkey) : Rsa () {
57105774 const int type = EVPKeyPointer::id (pkey);
57115775 if (type != EVP_PKEY_RSA && type != EVP_PKEY_RSA_PSS ) return ;
5776+ rsa_pss_ = type == EVP_PKEY_RSA_PSS ;
57125777 if (!GetPKeyBnParam (pkey, OSSL_PKEY_PARAM_RSA_N , &n_) ||
57135778 !GetPKeyBnParam (pkey, OSSL_PKEY_PARAM_RSA_E , &e_)) {
57145779 return ;
@@ -5804,7 +5869,35 @@ BIOPointer Rsa::derPublicKey() const {
58045869 if (!bio) return {};
58055870#if NCRYPTO_USE_OPENSSL3_PROVIDER
58065871 auto pkey = EVPKeyPointer::NewRSA (*this );
5807- if (!pkey || i2d_PUBKEY_bio (bio.get (), pkey.get ()) != 1 ) return {};
5872+ if (!pkey) return {};
5873+ if (!rsa_pss_) {
5874+ if (i2d_PUBKEY_bio (bio.get (), pkey.get ()) != 1 ) return {};
5875+ return bio;
5876+ }
5877+
5878+ X509_PUBKEY * raw_pubkey = nullptr ;
5879+ const int result = X509_PUBKEY_set (&raw_pubkey, pkey.get ());
5880+ X509PubkeyPointer pubkey (raw_pubkey);
5881+ if (result != 1 ) return {};
5882+
5883+ int parameter_type = V_ASN1_UNDEF ;
5884+ ASN1StringPointer parameters;
5885+ if (pss_params_) {
5886+ parameters = EncodeRsaPssParams (*pss_params_);
5887+ if (!parameters) return {};
5888+ parameter_type = V_ASN1_SEQUENCE ;
5889+ }
5890+
5891+ if (X509_PUBKEY_set0_param (pubkey.get (),
5892+ OBJ_nid2obj (NID_rsaEncryption),
5893+ parameter_type,
5894+ parameters.get (),
5895+ nullptr ,
5896+ 0 ) != 1 ) {
5897+ return {};
5898+ }
5899+ parameters.release ();
5900+ if (i2d_X509_PUBKEY_bio (bio.get (), pubkey.get ()) != 1 ) return {};
58085901#else
58095902 if (rsa_ == nullptr || i2d_RSA_PUBKEY_bio (bio.get (), rsa_) != 1 ) return {};
58105903#endif
0 commit comments