@@ -83,72 +83,91 @@ VALUE eDSAError;
8383static VALUE
8484ossl_dsa_initialize (int argc , VALUE * argv , VALUE self )
8585{
86- EVP_PKEY * pkey , * tmp ;
87- DSA * dsa = NULL ;
88- BIO * in ;
86+ EVP_PKEY * pkey ;
87+ DSA * dsa ;
88+ BIO * in = NULL ;
8989 VALUE arg , pass ;
90+ int type ;
91+
92+ TypedData_Get_Struct (self , EVP_PKEY , & ossl_evp_pkey_type , pkey );
93+ if (pkey )
94+ rb_raise (rb_eTypeError , "pkey already initialized" );
9095
91- GetPKey (self , pkey );
9296 /* The DSA.new(size, generator) form is handled by lib/openssl/pkey.rb */
9397 rb_scan_args (argc , argv , "02" , & arg , & pass );
9498 if (argc == 0 ) {
9599 dsa = DSA_new ();
96100 if (!dsa )
97101 ossl_raise (eDSAError , "DSA_new" );
102+ goto legacy ;
98103 }
99- else {
100- pass = ossl_pem_passwd_value (pass );
101- arg = ossl_to_der_if_possible (arg );
102- in = ossl_obj2bio (& arg );
103-
104- tmp = ossl_pkey_read_generic (in , pass );
105- if (tmp ) {
106- if (EVP_PKEY_base_id (tmp ) != EVP_PKEY_DSA )
107- rb_raise (eDSAError , "incorrect pkey type: %s" ,
108- OBJ_nid2sn (EVP_PKEY_base_id (tmp )));
109- dsa = EVP_PKEY_get1_DSA (tmp );
110- EVP_PKEY_free (tmp );
111- }
112- if (!dsa ) {
113- OSSL_BIO_reset (in );
114- #define PEM_read_bio_DSAPublicKey (bp ,x ,cb ,u ) (DSA *)PEM_ASN1_read_bio( \
115- (d2i_of_void *)d2i_DSAPublicKey, PEM_STRING_DSA_PUBLIC, (bp), (void **)(x), (cb), (u))
116- dsa = PEM_read_bio_DSAPublicKey (in , NULL , NULL , NULL );
117- #undef PEM_read_bio_DSAPublicKey
118- }
119- BIO_free (in );
120- if (!dsa ) {
121- ossl_clear_error ();
122- ossl_raise (eDSAError , "Neither PUB key nor PRIV key" );
123- }
124- }
125- if (!EVP_PKEY_assign_DSA (pkey , dsa )) {
126- DSA_free (dsa );
127- ossl_raise (eDSAError , NULL );
104+
105+ pass = ossl_pem_passwd_value (pass );
106+ arg = ossl_to_der_if_possible (arg );
107+ in = ossl_obj2bio (& arg );
108+
109+ /* DER-encoded DSAPublicKey format isn't supported by the generic routine */
110+ dsa = (DSA * )PEM_ASN1_read_bio ((d2i_of_void * )d2i_DSAPublicKey ,
111+ PEM_STRING_DSA_PUBLIC ,
112+ in , NULL , NULL , NULL );
113+ if (dsa )
114+ goto legacy ;
115+ OSSL_BIO_reset (in );
116+
117+ pkey = ossl_pkey_read_generic (in , pass );
118+ BIO_free (in );
119+ if (!pkey )
120+ ossl_raise (eDSAError , "Neither PUB key nor PRIV key" );
121+
122+ type = EVP_PKEY_base_id (pkey );
123+ if (type != EVP_PKEY_DSA ) {
124+ EVP_PKEY_free (pkey );
125+ rb_raise (eDSAError , "incorrect pkey type: %s" , OBJ_nid2sn (type ));
128126 }
127+ RTYPEDDATA_DATA (self ) = pkey ;
128+ return self ;
129129
130+ legacy :
131+ BIO_free (in );
132+ pkey = EVP_PKEY_new ();
133+ if (!pkey || EVP_PKEY_assign_DSA (pkey , dsa ) != 1 ) {
134+ EVP_PKEY_free (pkey );
135+ DSA_free (dsa );
136+ ossl_raise (eDSAError , "EVP_PKEY_assign_DSA" );
137+ }
138+ RTYPEDDATA_DATA (self ) = pkey ;
130139 return self ;
131140}
132141
142+ #ifndef HAVE_EVP_PKEY_DUP
133143static VALUE
134144ossl_dsa_initialize_copy (VALUE self , VALUE other )
135145{
136146 EVP_PKEY * pkey ;
137147 DSA * dsa , * dsa_new ;
138148
139- GetPKey (self , pkey );
140- if (EVP_PKEY_base_id ( pkey ) != EVP_PKEY_NONE )
141- ossl_raise ( eDSAError , "DSA already initialized" );
149+ TypedData_Get_Struct (self , EVP_PKEY , & ossl_evp_pkey_type , pkey );
150+ if (pkey )
151+ rb_raise ( rb_eTypeError , "pkey already initialized" );
142152 GetDSA (other , dsa );
143153
144- dsa_new = ASN1_dup ((i2d_of_void * )i2d_DSAPrivateKey , (d2i_of_void * )d2i_DSAPrivateKey , (char * )dsa );
154+ dsa_new = (DSA * )ASN1_dup ((i2d_of_void * )i2d_DSAPrivateKey ,
155+ (d2i_of_void * )d2i_DSAPrivateKey ,
156+ (char * )dsa );
145157 if (!dsa_new )
146158 ossl_raise (eDSAError , "ASN1_dup" );
147159
148- EVP_PKEY_assign_DSA (pkey , dsa_new );
160+ pkey = EVP_PKEY_new ();
161+ if (!pkey || EVP_PKEY_assign_DSA (pkey , dsa_new ) != 1 ) {
162+ EVP_PKEY_free (pkey );
163+ DSA_free (dsa_new );
164+ ossl_raise (eDSAError , "EVP_PKEY_assign_DSA" );
165+ }
166+ RTYPEDDATA_DATA (self ) = pkey ;
149167
150168 return self ;
151169}
170+ #endif
152171
153172/*
154173 * call-seq:
@@ -310,7 +329,9 @@ Init_ossl_dsa(void)
310329 cDSA = rb_define_class_under (mPKey , "DSA" , cPKey );
311330
312331 rb_define_method (cDSA , "initialize" , ossl_dsa_initialize , -1 );
332+ #ifndef HAVE_EVP_PKEY_DUP
313333 rb_define_method (cDSA , "initialize_copy" , ossl_dsa_initialize_copy , 1 );
334+ #endif
314335
315336 rb_define_method (cDSA , "public?" , ossl_dsa_is_public , 0 );
316337 rb_define_method (cDSA , "private?" , ossl_dsa_is_private , 0 );
0 commit comments