@@ -132,100 +132,85 @@ ossl_cipher_reset(VALUE self)
132
132
}
133
133
134
134
static VALUE
135
- ossl_cipher_encrypt (int argc , VALUE * argv , VALUE self )
135
+ ossl_cipher_init (int argc , VALUE * argv , VALUE self , int mode )
136
136
{
137
137
EVP_CIPHER_CTX * ctx ;
138
- unsigned char iv [EVP_MAX_IV_LENGTH ], key [EVP_MAX_KEY_LENGTH ];
138
+ unsigned char key [EVP_MAX_KEY_LENGTH ], * p_key = NULL ;
139
+ unsigned char iv [EVP_MAX_IV_LENGTH ], * p_iv = NULL ;
139
140
VALUE pass , init_v ;
140
141
141
142
GetCipher (self , ctx );
142
-
143
- rb_scan_args (argc , argv , "02" , & pass , & init_v );
144
-
145
- if (NIL_P (init_v )) {
143
+ if (rb_scan_args (argc , argv , "02" , & pass , & init_v ) > 0 ){
146
144
/*
147
- * TODO:
148
- * random IV generation!
149
- */
150
- memcpy (iv , "OpenSSL for Ruby rulez!" , sizeof (iv ));
151
- /*
152
- RAND_add(data,i,0); where from take data?
153
- if (RAND_pseudo_bytes(iv, 8) < 0) {
154
- ossl_raise(eCipherError, NULL);
155
- }
156
- */
157
- }
158
- else {
159
- init_v = rb_obj_as_string (init_v );
160
- if (EVP_MAX_IV_LENGTH > RSTRING (init_v )-> len ) {
161
- memset (iv , 0 , EVP_MAX_IV_LENGTH );
162
- memcpy (iv , RSTRING (init_v )-> ptr , RSTRING (init_v )-> len );
163
- }
164
- else {
165
- memcpy (iv , RSTRING (init_v )-> ptr , sizeof (iv ));
145
+ * oops. this code mistakes salt for IV.
146
+ * We deprecated the arguments for this method, but we decided
147
+ * keeping this behaviour for backward compatibility.
148
+ */
149
+ StringValue (pass );
150
+ if (NIL_P (init_v )) memcpy (iv , "OpenSSL for Ruby rulez!" , sizeof (iv ));
151
+ else {
152
+ char * cname = rb_class2name (rb_obj_class (self ));
153
+ rb_warning ("key derivation by %s#encrypt is deprecated; "
154
+ "use %s::pkcs5_keyivgen instead" , cname , cname );
155
+ StringValue (init_v );
156
+ if (EVP_MAX_IV_LENGTH > RSTRING (init_v )-> len ) {
157
+ memset (iv , 0 , EVP_MAX_IV_LENGTH );
158
+ memcpy (iv , RSTRING (init_v )-> ptr , RSTRING (init_v )-> len );
159
+ }
160
+ else memcpy (iv , RSTRING (init_v )-> ptr , sizeof (iv ));
166
161
}
162
+ EVP_BytesToKey (EVP_CIPHER_CTX_cipher (ctx ), EVP_md5 (), iv ,
163
+ RSTRING (pass )-> ptr , RSTRING (pass )-> len , 1 , key , NULL );
164
+ p_key = key ;
165
+ p_iv = iv ;
167
166
}
168
-
169
- if (EVP_CipherInit_ex (ctx , NULL , NULL , NULL , NULL , 1 ) != 1 ) {
170
- ossl_raise (eCipherError , NULL );
171
- }
172
-
173
- if (!NIL_P (pass )) {
174
- StringValue (pass );
175
-
176
- EVP_BytesToKey (EVP_CIPHER_CTX_cipher (ctx ), EVP_md5 (), iv ,
177
- RSTRING (pass )-> ptr , RSTRING (pass )-> len , 1 , key , NULL );
178
- if (EVP_CipherInit_ex (ctx , NULL , NULL , key , iv , -1 ) != 1 ) {
179
- ossl_raise (eCipherError , NULL );
180
- }
167
+ if (EVP_CipherInit_ex (ctx , NULL , NULL , p_key , p_iv , mode ) != 1 ) {
168
+ ossl_raise (eCipherError , NULL );
181
169
}
182
170
183
171
return self ;
184
172
}
185
173
186
174
static VALUE
187
- ossl_cipher_decrypt (int argc , VALUE * argv , VALUE self )
175
+ ossl_cipher_encrypt (int argc , VALUE * argv , VALUE self )
188
176
{
189
- EVP_CIPHER_CTX * ctx ;
190
- unsigned char iv [EVP_MAX_IV_LENGTH ], key [EVP_MAX_KEY_LENGTH ];
191
- VALUE pass , init_v ;
192
-
193
- GetCipher (self , ctx );
194
- rb_scan_args (argc , argv , "02" , & pass , & init_v );
195
-
196
- if (NIL_P (init_v )) {
197
- /*
198
- * TODO:
199
- * random IV generation!
200
- */
201
- memcpy (iv , "OpenSSL for Ruby rulez!" , EVP_MAX_IV_LENGTH );
202
- }
203
- else {
204
- init_v = rb_obj_as_string (init_v );
205
- if (EVP_MAX_IV_LENGTH > RSTRING (init_v )-> len ) {
206
- memset (iv , 0 , EVP_MAX_IV_LENGTH );
207
- memcpy (iv , RSTRING (init_v )-> ptr , RSTRING (init_v )-> len );
208
- }
209
- else {
210
- memcpy (iv , RSTRING (init_v )-> ptr , EVP_MAX_IV_LENGTH );
211
- }
212
- }
177
+ return ossl_cipher_init (argc , argv , self , 1 );
178
+ }
213
179
214
- if (EVP_CipherInit_ex (ctx , NULL , NULL , NULL , NULL , 0 ) != 1 ) {
215
- ossl_raise (eCipherError , NULL );
216
- }
180
+ static VALUE
181
+ ossl_cipher_decrypt (int argc , VALUE * argv , VALUE self )
182
+ {
183
+ return ossl_cipher_init (argc , argv , self , 0 );
184
+ }
217
185
218
- if (!NIL_P (pass )) {
219
- StringValue (pass );
186
+ static VALUE
187
+ ossl_cipher_pkcs5_keyivgen (int argc , VALUE * argv , VALUE self )
188
+ {
189
+ EVP_CIPHER_CTX * ctx ;
190
+ const EVP_MD * digest ;
191
+ VALUE vpass , vsalt , viter , vdigest ;
192
+ unsigned char key [EVP_MAX_KEY_LENGTH ], iv [EVP_MAX_IV_LENGTH ], * salt = NULL ;
193
+ int iter ;
220
194
221
- EVP_BytesToKey (EVP_CIPHER_CTX_cipher (ctx ), EVP_md5 (), iv ,
222
- RSTRING (pass )-> ptr , RSTRING (pass )-> len , 1 , key , NULL );
223
- if (EVP_CipherInit_ex (ctx , NULL , NULL , key , iv , -1 ) != 1 ) {
224
- ossl_raise (eCipherError , NULL );
225
- }
195
+ GetCipher (self , ctx );
196
+ rb_scan_args (argc , argv , "13" , & vpass , & vsalt , & viter , & vdigest );
197
+ StringValue (vpass );
198
+ if (!NIL_P (vsalt )){
199
+ StringValue (vsalt );
200
+ if (RSTRING (vsalt )-> len != PKCS5_SALT_LEN )
201
+ rb_raise (eCipherError , "salt must be an 8-octet string." );
202
+ salt = RSTRING (vsalt )-> ptr ;
226
203
}
204
+ iter = NIL_P (viter ) ? 2048 : NUM2INT (viter );
205
+ digest = NIL_P (vdigest ) ? EVP_md5 () : GetDigestPtr (vdigest );
206
+ EVP_BytesToKey (EVP_CIPHER_CTX_cipher (ctx ), digest , salt ,
207
+ RSTRING (vpass )-> ptr , RSTRING (vpass )-> len , iter , key , iv );
208
+ if (EVP_CipherInit_ex (ctx , NULL , NULL , key , iv , -1 ) != 1 )
209
+ ossl_raise (eCipherError , NULL );
210
+ OPENSSL_cleanse (key , sizeof key );
211
+ OPENSSL_cleanse (iv , sizeof iv );
227
212
228
- return self ;
213
+ return Qnil ;
229
214
}
230
215
231
216
static VALUE
@@ -312,14 +297,26 @@ ossl_cipher_set_iv(VALUE self, VALUE iv)
312
297
return iv ;
313
298
}
314
299
300
+ static VALUE
301
+ ossl_cipher_set_key_length (VALUE self , VALUE key_length )
302
+ {
303
+ EVP_CIPHER_CTX * ctx ;
304
+
305
+ GetCipher (self , ctx );
306
+ if (EVP_CIPHER_CTX_set_key_length (ctx , NUM2INT (key_length )) != 1 )
307
+ ossl_raise (eCipherError , NULL );
308
+
309
+ return key_length ;
310
+ }
311
+
315
312
static VALUE
316
313
ossl_cipher_set_padding (VALUE self , VALUE padding )
317
314
{
318
315
#if defined(HAVE_EVP_CIPHER_CTX_SET_PADDING )
319
316
EVP_CIPHER_CTX * ctx ;
320
317
321
318
GetCipher (self , ctx );
322
- if (EVP_CIPHER_CTX_set_padding (ctx , NUM2INT (padding )) != 1 )
319
+ if (EVP_CIPHER_CTX_set_padding (ctx , RTEST (padding )) != 1 )
323
320
ossl_raise (eCipherError , NULL );
324
321
#else
325
322
rb_notimplement ();
@@ -355,10 +352,12 @@ Init_ossl_cipher(void)
355
352
rb_define_method (cCipher , "reset" , ossl_cipher_reset , 0 );
356
353
rb_define_method (cCipher , "encrypt" , ossl_cipher_encrypt , -1 );
357
354
rb_define_method (cCipher , "decrypt" , ossl_cipher_decrypt , -1 );
355
+ rb_define_method (cCipher , "pkcs5_keyivgen" , ossl_cipher_pkcs5_keyivgen , -1 );
358
356
rb_define_method (cCipher , "update" , ossl_cipher_update , 1 );
359
357
rb_define_method (cCipher , "final" , ossl_cipher_final , 0 );
360
358
rb_define_method (cCipher , "name" , ossl_cipher_name , 0 );
361
359
rb_define_method (cCipher , "key=" , ossl_cipher_set_key , 1 );
360
+ rb_define_method (cCipher , "key_len=" , ossl_cipher_set_key_length , 1 );
362
361
rb_define_method (cCipher , "key_len" , ossl_cipher_key_length , 0 );
363
362
rb_define_method (cCipher , "iv=" , ossl_cipher_set_iv , 1 );
364
363
rb_define_method (cCipher , "iv_len" , ossl_cipher_iv_length , 0 );
0 commit comments