Ruby 1.9.2p136(2010-12-25revision30365)

- Main Page
- Modules
- Data Structures
- Files

- File List
- Globals

# ext/openssl/ossl_cipher.c

Go to the documentation of this file.

    00001 /*
    00002  * $Id: ossl_cipher.c 27440 2010-04-22 08:21:01Z nobu $
    00003  * 'OpenSSL for Ruby' project
    00004  * Copyright (C) 2001-2002  Michal Rokos <m.rokos@sh.cvut.cz>
    00005  * All rights reserved.
    00006  */
    00007 /*
    00008  * This program is licenced under the same licence as Ruby.
    00009  * (See the file 'LICENCE'.)
    00010  */
    00011 #include "ossl.h"
    00012
    00013 #define MakeCipher(obj, klass, ctx) \
    00014     obj = Data_Make_Struct(klass, EVP_CIPHER_CTX, 0, ossl_cipher_free, ctx)
    00015 #define GetCipher(obj, ctx) do { \
    00016     Data_Get_Struct(obj, EVP_CIPHER_CTX, ctx); \
    00017     if (!ctx) { \
    00018         ossl_raise(rb_eRuntimeError, "Cipher not inititalized!"); \
    00019     } \
    00020 } while (0)
    00021 #define SafeGetCipher(obj, ctx) do { \
    00022     OSSL_Check_Kind(obj, cCipher); \
    00023     GetCipher(obj, ctx); \
    00024 } while (0)
    00025
    00026 /*
    00027  * Classes
    00028  */
    00029 VALUE cCipher;
    00030 VALUE eCipherError;
    00031
    00032 static VALUE ossl_cipher_alloc(VALUE klass);
    00033
    00034 /*
    00035  * PUBLIC
    00036  */
    00037 const EVP_CIPHER *
    00038 GetCipherPtr(VALUE obj)
    00039 {
    00040     EVP_CIPHER_CTX *ctx;
    00041
    00042     SafeGetCipher(obj, ctx);
    00043
    00044     return EVP_CIPHER_CTX_cipher(ctx);
    00045 }
    00046
    00047 VALUE
    00048 ossl_cipher_new(const EVP_CIPHER *cipher)
    00049 {
    00050     VALUE ret;
    00051     EVP_CIPHER_CTX *ctx;
    00052
    00053     ret = ossl_cipher_alloc(cCipher);
    00054     GetCipher(ret, ctx);
    00055     EVP_CIPHER_CTX_init(ctx);
    00056     if (EVP_CipherInit_ex(ctx, cipher, NULL, NULL, NULL, -1) != 1)
    00057         ossl_raise(eCipherError, NULL);
    00058
    00059     return ret;
    00060 }
    00061
    00062 /*
    00063  * PRIVATE
    00064  */
    00065 static void
    00066 ossl_cipher_free(EVP_CIPHER_CTX *ctx)
    00067 {
    00068     if (ctx) {
    00069         EVP_CIPHER_CTX_cleanup(ctx);
    00070         ruby_xfree(ctx);
    00071     }
    00072 }
    00073
    00074 static VALUE
    00075 ossl_cipher_alloc(VALUE klass)
    00076 {
    00077     EVP_CIPHER_CTX *ctx;
    00078     VALUE obj;
    00079
    00080     MakeCipher(obj, klass, ctx);
    00081     EVP_CIPHER_CTX_init(ctx);
    00082
    00083     return obj;
    00084 }
    00085
    00086 /*
    00087  *  call-seq:
    00088  *     Cipher.new(string) -> cipher
    00089  *
    00090  *  The string must contain a valid cipher name like "AES-128-CBC" or "3DES".
    00091  *
    00092  *  A list of cipher names is available by calling OpenSSL::Cipher.ciphers.
    00093  */
    00094 static VALUE
    00095 ossl_cipher_initialize(VALUE self, VALUE str)
    00096 {
    00097     EVP_CIPHER_CTX *ctx;
    00098     const EVP_CIPHER *cipher;
    00099     char *name;
    00100
    00101     name = StringValuePtr(str);
    00102     GetCipher(self, ctx);
    00103     if (!(cipher = EVP_get_cipherbyname(name))) {
    00104         ossl_raise(rb_eRuntimeError, "unsupported cipher algorithm (%s)", name);
    00105     }
    00106     if (EVP_CipherInit_ex(ctx, cipher, NULL, NULL, NULL, -1) != 1)
    00107         ossl_raise(eCipherError, NULL);
    00108
    00109     return self;
    00110 }
    00111 static VALUE
    00112 ossl_cipher_copy(VALUE self, VALUE other)
    00113 {
    00114     EVP_CIPHER_CTX *ctx1, *ctx2;
    00115
    00116     rb_check_frozen(self);
    00117     if (self == other) return self;
    00118
    00119     GetCipher(self, ctx1);
    00120     SafeGetCipher(other, ctx2);
    00121     if (EVP_CIPHER_CTX_copy(ctx1, ctx2) != 1)
    00122         ossl_raise(eCipherError, NULL);
    00123
    00124     return self;
    00125 }
    00126
    00127 #ifdef HAVE_OBJ_NAME_DO_ALL_SORTED
    00128 static void*
    00129 add_cipher_name_to_ary(const OBJ_NAME *name, VALUE ary)
    00130 {
    00131     rb_ary_push(ary, rb_str_new2(name->name));
    00132     return NULL;
    00133 }
    00134 #endif
    00135
    00136 #ifdef HAVE_OBJ_NAME_DO_ALL_SORTED
    00137 /*
    00138  *  call-seq:
    00139  *     Cipher.ciphers -> array[string...]
    00140  *
    00141  *  Returns the names of all available ciphers in an array.
    00142  */
    00143 static VALUE
    00144 ossl_s_ciphers(VALUE self)
    00145 {
    00146     VALUE ary;
    00147
    00148     ary = rb_ary_new();
    00149     OBJ_NAME_do_all_sorted(OBJ_NAME_TYPE_CIPHER_METH,
    00150                     (void(*)(const OBJ_NAME*,void*))add_cipher_name_to_ary,
    00151                     (void*)ary);
    00152
    00153     return ary;
    00154 }
    00155 #else
    00156 #define ossl_s_ciphers rb_f_notimplement
    00157 #endif
    00158
    00159 /*
    00160  *  call-seq:
    00161  *     cipher.reset -> self
    00162  *
    00163  *  Internally calls EVP_CipherInit_ex(ctx, NULL, NULL, NULL, NULL, -1).
    00164  */
    00165 static VALUE
    00166 ossl_cipher_reset(VALUE self)
    00167 {
    00168     EVP_CIPHER_CTX *ctx;
    00169
    00170     GetCipher(self, ctx);
    00171     if (EVP_CipherInit_ex(ctx, NULL, NULL, NULL, NULL, -1) != 1)
    00172         ossl_raise(eCipherError, NULL);
    00173
    00174     return self;
    00175 }
    00176
    00177 static VALUE
    00178 ossl_cipher_init(int argc, VALUE *argv, VALUE self, int mode)
    00179 {
    00180     EVP_CIPHER_CTX *ctx;
    00181     unsigned char key[EVP_MAX_KEY_LENGTH], *p_key = NULL;
    00182     unsigned char iv[EVP_MAX_IV_LENGTH], *p_iv = NULL;
    00183     VALUE pass, init_v;
    00184
    00185     if(rb_scan_args(argc, argv, "02", &pass, &init_v) > 0){
    00186         /*
    00187          * oops. this code mistakes salt for IV.
    00188          * We deprecated the arguments for this method, but we decided
    00189          * keeping this behaviour for backward compatibility.
    00190          */
    00191         const char *cname  = rb_class2name(rb_obj_class(self));
    00192         rb_warn("argumtents for %s#encrypt and %s#decrypt were deprecated; "
    00193                 "use %s#pkcs5_keyivgen to derive key and IV",
    00194                 cname, cname, cname);
    00195         StringValue(pass);
    00196         GetCipher(self, ctx);
    00197         if (NIL_P(init_v)) memcpy(iv, "OpenSSL for Ruby rulez!", sizeof(iv));
    00198         else{
    00199             StringValue(init_v);
    00200             if (EVP_MAX_IV_LENGTH > RSTRING_LEN(init_v)) {
    00201                 memset(iv, 0, EVP_MAX_IV_LENGTH);
    00202                 memcpy(iv, RSTRING_PTR(init_v), RSTRING_LEN(init_v));
    00203             }
    00204             else memcpy(iv, RSTRING_PTR(init_v), sizeof(iv));
    00205         }
    00206         EVP_BytesToKey(EVP_CIPHER_CTX_cipher(ctx), EVP_md5(), iv,
    00207                        (unsigned char *)RSTRING_PTR(pass), RSTRING_LEN(pass), 1, key, NULL);
    00208         p_key = key;
    00209         p_iv = iv;
    00210     }
    00211     else {
    00212         GetCipher(self, ctx);
    00213     }
    00214     if (EVP_CipherInit_ex(ctx, NULL, NULL, p_key, p_iv, mode) != 1) {
    00215         ossl_raise(eCipherError, NULL);
    00216     }
    00217
    00218     return self;
    00219 }
    00220
    00221 /*
    00222  *  call-seq:
    00223  *     cipher.encrypt -> self
    00224  *
    00225  *  Make sure to call .encrypt or .decrypt before using any of the following methods:
    00226  *  * [key=, iv=, random_key, random_iv, pkcs5_keyivgen]
    00227  *
    00228  *  Internally calls EVP_CipherInit_ex(ctx, NULL, NULL, NULL, NULL, 1).
    00229  */
    00230 static VALUE
    00231 ossl_cipher_encrypt(int argc, VALUE *argv, VALUE self)
    00232 {
    00233     return ossl_cipher_init(argc, argv, self, 1);
    00234 }
    00235
    00236 /*
    00237  *  call-seq:
    00238  *     cipher.decrypt -> self
    00239  *
    00240  *  Make sure to call .encrypt or .decrypt before using any of the following methods:
    00241  *  * [key=, iv=, random_key, random_iv, pkcs5_keyivgen]
    00242  *
    00243  *  Internally calls EVP_CipherInit_ex(ctx, NULL, NULL, NULL, NULL, 0).
    00244  */
    00245 static VALUE
    00246 ossl_cipher_decrypt(int argc, VALUE *argv, VALUE self)
    00247 {
    00248     return ossl_cipher_init(argc, argv, self, 0);
    00249 }
    00250
    00251 /*
    00252  *  call-seq:
    00253  *     cipher.pkcs5_keyivgen(pass [, salt [, iterations [, digest]]] ) -> nil
    00254  *
    00255  *  Generates and sets the key/iv based on a password.
    00256  *
    00257  *  WARNING: This method is only PKCS5 v1.5 compliant when using RC2, RC4-40, or DES
    00258  *  with MD5 or SHA1.  Using anything else (like AES) will generate the key/iv using an
    00259  *  OpenSSL specific method.  Use a PKCS5 v2 key generation method instead.
    00260  *
    00261  *  === Parameters
    00262  *  +salt+ must be an 8 byte string if provided.
    00263  *  +iterations+ is a integer with a default of 2048.
    00264  *  +digest+ is a Digest object that defaults to 'MD5'
    00265  *
    00266  *  A minimum of 1000 iterations is recommended.
    00267  *
    00268  */
    00269 static VALUE
    00270 ossl_cipher_pkcs5_keyivgen(int argc, VALUE *argv, VALUE self)
    00271 {
    00272     EVP_CIPHER_CTX *ctx;
    00273     const EVP_MD *digest;
    00274     VALUE vpass, vsalt, viter, vdigest;
    00275     unsigned char key[EVP_MAX_KEY_LENGTH], iv[EVP_MAX_IV_LENGTH], *salt = NULL;
    00276     int iter;
    00277
    00278     rb_scan_args(argc, argv, "13", &vpass, &vsalt, &viter, &vdigest);
    00279     StringValue(vpass);
    00280     if(!NIL_P(vsalt)){
    00281         StringValue(vsalt);
    00282         if(RSTRING_LEN(vsalt) != PKCS5_SALT_LEN)
    00283             rb_raise(eCipherError, "salt must be an 8-octet string");
    00284         salt = (unsigned char *)RSTRING_PTR(vsalt);
    00285     }
    00286     iter = NIL_P(viter) ? 2048 : NUM2INT(viter);
    00287     digest = NIL_P(vdigest) ? EVP_md5() : GetDigestPtr(vdigest);
    00288     GetCipher(self, ctx);
    00289     EVP_BytesToKey(EVP_CIPHER_CTX_cipher(ctx), digest, salt,
    00290                    (unsigned char *)RSTRING_PTR(vpass), RSTRING_LEN(vpass), iter, key, iv);
    00291     if (EVP_CipherInit_ex(ctx, NULL, NULL, key, iv, -1) != 1)
    00292         ossl_raise(eCipherError, NULL);
    00293     OPENSSL_cleanse(key, sizeof key);
    00294     OPENSSL_cleanse(iv, sizeof iv);
    00295
    00296     return Qnil;
    00297 }
    00298
    00299
    00300 /*
    00301  *  call-seq:
    00302  *     cipher.update(data [, buffer]) -> string or buffer
    00303  *
    00304  *  === Parameters
    00305  *  +data+ is a nonempty string.
    00306  *  +buffer+ is an optional string to store the result.
    00307  */
    00308 static VALUE
    00309 ossl_cipher_update(int argc, VALUE *argv, VALUE self)
    00310 {
    00311     EVP_CIPHER_CTX *ctx;
    00312     unsigned char *in;
    00313     int in_len, out_len;
    00314     VALUE data, str;
    00315
    00316     rb_scan_args(argc, argv, "11", &data, &str);
    00317
    00318     StringValue(data);
    00319     in = (unsigned char *)RSTRING_PTR(data);
    00320     if ((in_len = RSTRING_LEN(data)) == 0)
    00321         rb_raise(rb_eArgError, "data must not be empty");
    00322     GetCipher(self, ctx);
    00323     out_len = in_len+EVP_CIPHER_CTX_block_size(ctx);
    00324
    00325     if (NIL_P(str)) {
    00326         str = rb_str_new(0, out_len);
    00327     } else {
    00328         StringValue(str);
    00329         rb_str_resize(str, out_len);
    00330     }
    00331
    00332     if (!EVP_CipherUpdate(ctx, (unsigned char *)RSTRING_PTR(str), &out_len, in, in_len))
    00333         ossl_raise(eCipherError, NULL);
    00334     assert(out_len < RSTRING_LEN(str));
    00335     rb_str_set_len(str, out_len);
    00336
    00337     return str;
    00338 }
    00339
    00340 /*
    00341  *  call-seq:
    00342  *     cipher.final -> aString
    00343  *
    00344  *  Returns the remaining data held in the cipher object.  Further calls to update() or final() will return garbage.
    00345  *
    00346  *  See EVP_CipherFinal_ex for further information.
    00347  */
    00348 static VALUE
    00349 ossl_cipher_final(VALUE self)
    00350 {
    00351     EVP_CIPHER_CTX *ctx;
    00352     int out_len;
    00353     VALUE str;
    00354
    00355     GetCipher(self, ctx);
    00356     str = rb_str_new(0, EVP_CIPHER_CTX_block_size(ctx));
    00357     if (!EVP_CipherFinal_ex(ctx, (unsigned char *)RSTRING_PTR(str), &out_len))
    00358         ossl_raise(eCipherError, NULL);
    00359     assert(out_len <= RSTRING_LEN(str));
    00360     rb_str_set_len(str, out_len);
    00361
    00362     return str;
    00363 }
    00364
    00365 /*
    00366  *  call-seq:
    00367  *     cipher.name -> string
    00368  *
    00369  *  Returns the name of the cipher which may differ slightly from the original name provided.
    00370  */
    00371 static VALUE
    00372 ossl_cipher_name(VALUE self)
    00373 {
    00374     EVP_CIPHER_CTX *ctx;
    00375
    00376     GetCipher(self, ctx);
    00377
    00378     return rb_str_new2(EVP_CIPHER_name(EVP_CIPHER_CTX_cipher(ctx)));
    00379 }
    00380
    00381 /*
    00382  *  call-seq:
    00383  *     cipher.key = string -> string
    00384  *
    00385  *  Sets the cipher key.
    00386  *
    00387  *  Only call this method after calling cipher.encrypt or cipher.decrypt.
    00388  */
    00389 static VALUE
    00390 ossl_cipher_set_key(VALUE self, VALUE key)
    00391 {
    00392     EVP_CIPHER_CTX *ctx;
    00393
    00394     StringValue(key);
    00395     GetCipher(self, ctx);
    00396
    00397     if (RSTRING_LEN(key) < EVP_CIPHER_CTX_key_length(ctx))
    00398         ossl_raise(eCipherError, "key length too short");
    00399
    00400     if (EVP_CipherInit_ex(ctx, NULL, NULL, (unsigned char *)RSTRING_PTR(key), NULL, -1) != 1)
    00401         ossl_raise(eCipherError, NULL);
    00402
    00403     return key;
    00404 }
    00405
    00406 /*
    00407  *  call-seq:
    00408  *     cipher.iv = string -> string
    00409  *
    00410  *  Sets the cipher iv.
    00411  *
    00412  *  Only call this method after calling cipher.encrypt or cipher.decrypt.
    00413  */
    00414 static VALUE
    00415 ossl_cipher_set_iv(VALUE self, VALUE iv)
    00416 {
    00417     EVP_CIPHER_CTX *ctx;
    00418
    00419     StringValue(iv);
    00420     GetCipher(self, ctx);
    00421
    00422     if (RSTRING_LEN(iv) < EVP_CIPHER_CTX_iv_length(ctx))
    00423         ossl_raise(eCipherError, "iv length too short");
    00424
    00425     if (EVP_CipherInit_ex(ctx, NULL, NULL, NULL, (unsigned char *)RSTRING_PTR(iv), -1) != 1)
    00426         ossl_raise(eCipherError, NULL);
    00427
    00428     return iv;
    00429 }
    00430
    00431
    00432 /*
    00433  *  call-seq:
    00434  *     cipher.key_length = integer -> integer
    00435  *
    00436  *  Sets the key length of the cipher.  If the cipher is a fixed length cipher then attempting to set the key
    00437  *  length to any value other than the fixed value is an error.
    00438  *
    00439  *  Under normal circumstances you do not need to call this method (and probably shouldn't).
    00440  *
    00441  *  See EVP_CIPHER_CTX_set_key_length for further information.
    00442  */
    00443 static VALUE
    00444 ossl_cipher_set_key_length(VALUE self, VALUE key_length)
    00445 {
    00446     int len = NUM2INT(key_length);
    00447     EVP_CIPHER_CTX *ctx;
    00448
    00449     GetCipher(self, ctx);
    00450     if (EVP_CIPHER_CTX_set_key_length(ctx, len) != 1)
    00451         ossl_raise(eCipherError, NULL);
    00452
    00453     return key_length;
    00454 }
    00455
    00456 #if defined(HAVE_EVP_CIPHER_CTX_SET_PADDING)
    00457 /*
    00458  *  call-seq:
    00459  *     cipher.padding = integer -> integer
    00460  *
    00461  *  Enables or disables padding. By default encryption operations are padded using standard block padding and the
    00462  *  padding is checked and removed when decrypting. If the pad parameter is zero then no padding is performed, the
    00463  *  total amount of data encrypted or decrypted must then be a multiple of the block size or an error will occur.
    00464  *
    00465  *  See EVP_CIPHER_CTX_set_padding for further information.
    00466  */
    00467 static VALUE
    00468 ossl_cipher_set_padding(VALUE self, VALUE padding)
    00469 {
    00470     EVP_CIPHER_CTX *ctx;
    00471     int pad = NUM2INT(padding);
    00472
    00473     GetCipher(self, ctx);
    00474     if (EVP_CIPHER_CTX_set_padding(ctx, pad) != 1)
    00475         ossl_raise(eCipherError, NULL);
    00476     return padding;
    00477 }
    00478 #else
    00479 #define ossl_cipher_set_padding rb_f_notimplement
    00480 #endif
    00481
    00482 #define CIPHER_0ARG_INT(func)                                   \
    00483     static VALUE                                                \
    00484     ossl_cipher_##func(VALUE self)                              \
    00485     {                                                           \
    00486         EVP_CIPHER_CTX *ctx;                                    \
    00487         GetCipher(self, ctx);                                   \
    00488         return INT2NUM(EVP_CIPHER_##func(EVP_CIPHER_CTX_cipher(ctx)));  \
    00489     }
    00490 CIPHER_0ARG_INT(key_length)
    00491 CIPHER_0ARG_INT(iv_length)
    00492 CIPHER_0ARG_INT(block_size)
    00493
    00494 #if 0
    00495 /*
    00496  *  call-seq:
    00497  *     cipher.key_length -> integer
    00498  *
    00499  */
    00500 static VALUE ossl_cipher_key_length() { }
    00501 /*
    00502  *  call-seq:
    00503  *     cipher.iv_length -> integer
    00504  *
    00505  */
    00506 static VALUE ossl_cipher_iv_length() { }
    00507 /*
    00508  *  call-seq:
    00509  *     cipher.block_size -> integer
    00510  *
    00511  */
    00512 static VALUE ossl_cipher_block_size() { }
    00513 #endif
    00514
    00515 /*
    00516  * INIT
    00517  */
    00518 void
    00519 Init_ossl_cipher(void)
    00520 {
    00521 #if 0 /* let rdoc know about mOSSL */
    00522     mOSSL = rb_define_module("OpenSSL");
    00523 #endif
    00524     cCipher = rb_define_class_under(mOSSL, "Cipher", rb_cObject);
    00525     eCipherError = rb_define_class_under(cCipher, "CipherError", eOSSLError);
    00526
    00527     rb_define_alloc_func(cCipher, ossl_cipher_alloc);
    00528     rb_define_copy_func(cCipher, ossl_cipher_copy);
    00529     rb_define_module_function(cCipher, "ciphers", ossl_s_ciphers, 0);
    00530     rb_define_method(cCipher, "initialize", ossl_cipher_initialize, 1);
    00531     rb_define_method(cCipher, "reset", ossl_cipher_reset, 0);
    00532     rb_define_method(cCipher, "encrypt", ossl_cipher_encrypt, -1);
    00533     rb_define_method(cCipher, "decrypt", ossl_cipher_decrypt, -1);
    00534     rb_define_method(cCipher, "pkcs5_keyivgen", ossl_cipher_pkcs5_keyivgen, -1);
    00535     rb_define_method(cCipher, "update", ossl_cipher_update, -1);
    00536     rb_define_method(cCipher, "final", ossl_cipher_final, 0);
    00537     rb_define_method(cCipher, "name", ossl_cipher_name, 0);
    00538     rb_define_method(cCipher, "key=", ossl_cipher_set_key, 1);
    00539     rb_define_method(cCipher, "key_len=", ossl_cipher_set_key_length, 1);
    00540     rb_define_method(cCipher, "key_len", ossl_cipher_key_length, 0);
    00541     rb_define_method(cCipher, "iv=", ossl_cipher_set_iv, 1);
    00542     rb_define_method(cCipher, "iv_len", ossl_cipher_iv_length, 0);
    00543     rb_define_method(cCipher, "block_size", ossl_cipher_block_size, 0);
    00544     rb_define_method(cCipher, "padding=", ossl_cipher_set_padding, 1);
    00545 }
    00546
    00547