@@ -95,34 +95,30 @@ const rb_data_type_t ossl_evp_pkey_type = {
9595static VALUE
9696pkey_new0 (EVP_PKEY * pkey )
9797{
98- VALUE obj ;
98+ VALUE klass , obj ;
9999 int type ;
100100
101101 if (!pkey || (type = EVP_PKEY_base_id (pkey )) == EVP_PKEY_NONE )
102102 ossl_raise (rb_eRuntimeError , "pkey is empty" );
103103
104104 switch (type ) {
105105#if !defined(OPENSSL_NO_RSA )
106- case EVP_PKEY_RSA :
107- return ossl_rsa_new (pkey );
106+ case EVP_PKEY_RSA : klass = cRSA ; break ;
108107#endif
109108#if !defined(OPENSSL_NO_DSA )
110- case EVP_PKEY_DSA :
111- return ossl_dsa_new (pkey );
109+ case EVP_PKEY_DSA : klass = cDSA ; break ;
112110#endif
113111#if !defined(OPENSSL_NO_DH )
114- case EVP_PKEY_DH :
115- return ossl_dh_new (pkey );
112+ case EVP_PKEY_DH : klass = cDH ; break ;
116113#endif
117114#if !defined(OPENSSL_NO_EC )
118- case EVP_PKEY_EC :
119- return ossl_ec_new (pkey );
115+ case EVP_PKEY_EC : klass = cEC ; break ;
120116#endif
121- default :
122- obj = NewPKey (cPKey );
123- SetPKey (obj , pkey );
124- return obj ;
117+ default : klass = cPKey ; break ;
125118 }
119+ obj = NewPKey (klass );
120+ SetPKey (obj , pkey );
121+ return obj ;
126122}
127123
128124VALUE
@@ -140,6 +136,35 @@ ossl_pkey_new(EVP_PKEY *pkey)
140136 return obj ;
141137}
142138
139+ EVP_PKEY *
140+ ossl_pkey_read_generic (BIO * bio , VALUE pass )
141+ {
142+ void * ppass = (void * )pass ;
143+ EVP_PKEY * pkey ;
144+
145+ if ((pkey = d2i_PrivateKey_bio (bio , NULL )))
146+ goto out ;
147+ OSSL_BIO_reset (bio );
148+ if ((pkey = d2i_PKCS8PrivateKey_bio (bio , NULL , ossl_pem_passwd_cb , ppass )))
149+ goto out ;
150+ OSSL_BIO_reset (bio );
151+ if ((pkey = d2i_PUBKEY_bio (bio , NULL )))
152+ goto out ;
153+ OSSL_BIO_reset (bio );
154+ /* PEM_read_bio_PrivateKey() also parses PKCS #8 formats */
155+ if ((pkey = PEM_read_bio_PrivateKey (bio , NULL , ossl_pem_passwd_cb , ppass )))
156+ goto out ;
157+ OSSL_BIO_reset (bio );
158+ if ((pkey = PEM_read_bio_PUBKEY (bio , NULL , NULL , NULL )))
159+ goto out ;
160+ OSSL_BIO_reset (bio );
161+ if ((pkey = PEM_read_bio_Parameters (bio , NULL )))
162+ goto out ;
163+
164+ out :
165+ return pkey ;
166+ }
167+
143168/*
144169 * call-seq:
145170 * OpenSSL::PKey.read(string [, pwd ]) -> PKey
@@ -164,30 +189,11 @@ ossl_pkey_new_from_data(int argc, VALUE *argv, VALUE self)
164189 VALUE data , pass ;
165190
166191 rb_scan_args (argc , argv , "11" , & data , & pass );
167- pass = ossl_pem_passwd_value (pass );
168-
169192 bio = ossl_obj2bio (& data );
170- if ((pkey = d2i_PrivateKey_bio (bio , NULL )))
171- goto ok ;
172- OSSL_BIO_reset (bio );
173- if ((pkey = d2i_PKCS8PrivateKey_bio (bio , NULL , ossl_pem_passwd_cb , (void * )pass )))
174- goto ok ;
175- OSSL_BIO_reset (bio );
176- if ((pkey = d2i_PUBKEY_bio (bio , NULL )))
177- goto ok ;
178- OSSL_BIO_reset (bio );
179- /* PEM_read_bio_PrivateKey() also parses PKCS #8 formats */
180- if ((pkey = PEM_read_bio_PrivateKey (bio , NULL , ossl_pem_passwd_cb , (void * )pass )))
181- goto ok ;
182- OSSL_BIO_reset (bio );
183- if ((pkey = PEM_read_bio_PUBKEY (bio , NULL , NULL , NULL )))
184- goto ok ;
185-
186- BIO_free (bio );
187- ossl_raise (ePKeyError , "Could not parse PKey" );
188-
189- ok :
193+ pkey = ossl_pkey_read_generic (bio , ossl_pem_passwd_value (pass ));
190194 BIO_free (bio );
195+ if (!pkey )
196+ ossl_raise (ePKeyError , "Could not parse PKey" );
191197 return ossl_pkey_new (pkey );
192198}
193199
@@ -335,6 +341,52 @@ ossl_pkey_inspect(VALUE self)
335341 OBJ_nid2sn (nid ));
336342}
337343
344+ VALUE
345+ ossl_pkey_export_traditional (int argc , VALUE * argv , VALUE self , int to_der )
346+ {
347+ EVP_PKEY * pkey ;
348+ VALUE cipher , pass ;
349+ const EVP_CIPHER * enc = NULL ;
350+ BIO * bio ;
351+
352+ GetPKey (self , pkey );
353+ rb_scan_args (argc , argv , "02" , & cipher , & pass );
354+ if (!NIL_P (cipher )) {
355+ enc = ossl_evp_get_cipherbyname (cipher );
356+ pass = ossl_pem_passwd_value (pass );
357+ }
358+
359+ bio = BIO_new (BIO_s_mem ());
360+ if (!bio )
361+ ossl_raise (ePKeyError , "BIO_new" );
362+ if (to_der ) {
363+ if (!i2d_PrivateKey_bio (bio , pkey )) {
364+ BIO_free (bio );
365+ ossl_raise (ePKeyError , "i2d_PrivateKey_bio" );
366+ }
367+ }
368+ else {
369+ #if OPENSSL_VERSION_NUMBER >= 0x10100000 && !defined(LIBRESSL_VERSION_NUMBER )
370+ if (!PEM_write_bio_PrivateKey_traditional (bio , pkey , enc , NULL , 0 ,
371+ ossl_pem_passwd_cb ,
372+ (void * )pass )) {
373+ #else
374+ char pem_str [80 ];
375+ const char * aname ;
376+
377+ EVP_PKEY_asn1_get0_info (NULL , NULL , NULL , NULL , & aname , pkey -> ameth );
378+ snprintf (pem_str , sizeof (pem_str ), "%s PRIVATE KEY" , aname );
379+ if (!PEM_ASN1_write_bio ((i2d_of_void * )i2d_PrivateKey , pem_str , bio ,
380+ pkey , enc , NULL , 0 , ossl_pem_passwd_cb ,
381+ (void * )pass )) {
382+ #endif
383+ BIO_free (bio );
384+ ossl_raise (ePKeyError , "PEM_write_bio_PrivateKey_traditional" );
385+ }
386+ }
387+ return ossl_membio2str (bio );
388+ }
389+
338390static VALUE
339391do_pkcs8_export (int argc , VALUE * argv , VALUE self , int to_der )
340392{
@@ -404,8 +456,8 @@ ossl_pkey_private_to_pem(int argc, VALUE *argv, VALUE self)
404456 return do_pkcs8_export (argc , argv , self , 0 );
405457}
406458
407- static VALUE
408- do_spki_export (VALUE self , int to_der )
459+ VALUE
460+ ossl_pkey_export_spki (VALUE self , int to_der )
409461{
410462 EVP_PKEY * pkey ;
411463 BIO * bio ;
@@ -438,7 +490,7 @@ do_spki_export(VALUE self, int to_der)
438490static VALUE
439491ossl_pkey_public_to_der (VALUE self )
440492{
441- return do_spki_export (self , 1 );
493+ return ossl_pkey_export_spki (self , 1 );
442494}
443495
444496/*
@@ -450,7 +502,7 @@ ossl_pkey_public_to_der(VALUE self)
450502static VALUE
451503ossl_pkey_public_to_pem (VALUE self )
452504{
453- return do_spki_export (self , 0 );
505+ return ossl_pkey_export_spki (self , 0 );
454506}
455507
456508/*
0 commit comments