|
Ruby 1.9.2p290(2011-07-09revision32553)
|
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
1.7.3