@@ -83,23 +83,69 @@ ossl_pkey_new(EVP_PKEY *pkey)
8383# include <openssl/decoder.h>
8484
8585EVP_PKEY *
86- ossl_pkey_read_generic (BIO * bio , VALUE pass )
86+ ossl_pkey_read (BIO * bio , const char * input_type , int selection , VALUE pass )
8787{
8888 void * ppass = (void * )pass ;
89- OSSL_DECODER_CTX * dctx ;
89+ OSSL_DECODER_CTX * dctx = NULL ;
9090 EVP_PKEY * pkey = NULL ;
91- int pos = 0 , pos2 ;
91+ int pos = 0 , pos2 = 0 ;
9292
93- dctx = OSSL_DECODER_CTX_new_for_pkey (& pkey , "DER" , NULL , NULL , 0 , NULL , NULL );
93+ dctx = OSSL_DECODER_CTX_new_for_pkey (& pkey , input_type , NULL , NULL ,
94+ selection , NULL , NULL );
9495 if (!dctx )
9596 goto out ;
96- if (OSSL_DECODER_CTX_set_pem_password_cb (dctx , ossl_pem_passwd_cb , ppass ) != 1 )
97+ if (OSSL_DECODER_CTX_set_pem_password_cb (dctx , ossl_pem_passwd_cb ,
98+ ppass ) != 1 )
9799 goto out ;
100+ while (1 ) {
101+ if (OSSL_DECODER_from_bio (dctx , bio ) == 1 )
102+ goto out ;
103+ if (BIO_eof (bio ))
104+ break ;
105+ pos2 = BIO_tell (bio );
106+ if (pos2 < 0 || pos2 <= pos )
107+ break ;
108+ ossl_clear_error ();
109+ pos = pos2 ;
110+ }
111+ out :
112+ OSSL_BIO_reset (bio );
113+ OSSL_DECODER_CTX_free (dctx );
114+ return pkey ;
115+ }
116+
117+ EVP_PKEY *
118+ ossl_pkey_read_generic (BIO * bio , VALUE pass )
119+ {
120+ EVP_PKEY * pkey = NULL ;
121+ /* Non-zero selections to try to decode.
122+ *
123+ * See EVP_PKEY_fromdata(3) - Selections to see all the selections.
124+ *
125+ * This is a workaround for the decoder failing to decode or returning
126+ * bogus keys with selection 0, if a key management provider is different
127+ * from a decoder provider. The workaround is to avoid using selection 0.
128+ *
129+ * Affected OpenSSL versions: >= 3.1.0, <= 3.1.2, or >= 3.0.0, <= 3.0.10
130+ * Fixed OpenSSL versions: 3.2, next release of the 3.1.z and 3.0.z
131+ *
132+ * See <https://github.com/openssl/openssl/pull/21519> for details.
133+ */
134+ int selections [] = {
135+ EVP_PKEY_KEY_PARAMETERS ,
136+ EVP_PKEY_PUBLIC_KEY ,
137+ EVP_PKEY_KEYPAIR
138+ };
139+ int i = 0 ;
140+ int selection_num = sizeof (selections ) / sizeof (int );
98141
99142 /* First check DER */
100- if (OSSL_DECODER_from_bio (dctx , bio ) == 1 )
101- goto out ;
102- OSSL_BIO_reset (bio );
143+ for (i = 0 ; i < selection_num ; i ++ ) {
144+ pkey = ossl_pkey_read (bio , "DER" , selections [i ], pass );
145+ if (pkey ) {
146+ goto out ;
147+ }
148+ }
103149
104150 /*
105151 * Then check PEM; multiple OSSL_DECODER_from_bio() calls may be needed.
@@ -128,48 +174,18 @@ ossl_pkey_read_generic(BIO *bio, VALUE pass)
128174 * we use the different selection as a workaround.
129175 * https://github.com/openssl/openssl/issues/20657
130176 */
131- OSSL_DECODER_CTX_free (dctx );
132- dctx = NULL ;
133- dctx = OSSL_DECODER_CTX_new_for_pkey (& pkey , "PEM" , NULL , NULL ,
134- EVP_PKEY_KEYPAIR , NULL , NULL );
135- if (!dctx )
136- goto out ;
137- if (OSSL_DECODER_CTX_set_pem_password_cb (dctx , ossl_pem_passwd_cb , ppass ) != 1 )
177+ pkey = ossl_pkey_read (bio , "PEM" , EVP_PKEY_KEYPAIR , pass );
178+ if (pkey ) {
138179 goto out ;
139- while (1 ) {
140- if (OSSL_DECODER_from_bio (dctx , bio ) == 1 )
141- goto out ;
142- if (BIO_eof (bio ))
143- break ;
144- pos2 = BIO_tell (bio );
145- if (pos2 < 0 || pos2 <= pos )
146- break ;
147- ossl_clear_error ();
148- pos = pos2 ;
149180 }
150181
151- OSSL_BIO_reset (bio );
152- OSSL_DECODER_CTX_free (dctx );
153- dctx = NULL ;
154- dctx = OSSL_DECODER_CTX_new_for_pkey (& pkey , "PEM" , NULL , NULL , 0 , NULL , NULL );
155- if (!dctx )
156- goto out ;
157- if (OSSL_DECODER_CTX_set_pem_password_cb (dctx , ossl_pem_passwd_cb , ppass ) != 1 )
158- goto out ;
159- while (1 ) {
160- if (OSSL_DECODER_from_bio (dctx , bio ) == 1 )
182+ for (i = 0 ; i < selection_num ; i ++ ) {
183+ pkey = ossl_pkey_read (bio , "PEM" , selections [i ], pass );
184+ if (pkey ) {
161185 goto out ;
162- if (BIO_eof (bio ))
163- break ;
164- pos2 = BIO_tell (bio );
165- if (pos2 < 0 || pos2 <= pos )
166- break ;
167- ossl_clear_error ();
168- pos = pos2 ;
186+ }
169187 }
170-
171188 out :
172- OSSL_DECODER_CTX_free (dctx );
173189 return pkey ;
174190}
175191#else
0 commit comments