Ruby
2.0.0p247(2013-06-27revision41674)
|
00001 /* 00002 * $Id: ossl_engine.c 33634 2011-11-04 07:19:23Z nobu $ 00003 * 'OpenSSL for Ruby' project 00004 * Copyright (C) 2003 GOTOU Yuuzou <gotoyuzo@notwork.org> 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 #if defined(OSSL_ENGINE_ENABLED) 00014 00015 #define WrapEngine(klass, obj, engine) do { \ 00016 if (!(engine)) { \ 00017 ossl_raise(rb_eRuntimeError, "ENGINE wasn't initialized."); \ 00018 } \ 00019 (obj) = Data_Wrap_Struct((klass), 0, ENGINE_free, (engine)); \ 00020 } while(0) 00021 #define GetEngine(obj, engine) do { \ 00022 Data_Get_Struct((obj), ENGINE, (engine)); \ 00023 if (!(engine)) { \ 00024 ossl_raise(rb_eRuntimeError, "ENGINE wasn't initialized."); \ 00025 } \ 00026 } while (0) 00027 #define SafeGetEngine(obj, engine) do { \ 00028 OSSL_Check_Kind((obj), cEngine); \ 00029 GetPKCS7((obj), (engine)); \ 00030 } while (0) 00031 00032 /* 00033 * Classes 00034 */ 00035 VALUE cEngine; 00036 VALUE eEngineError; 00037 00038 /* 00039 * Private 00040 */ 00041 #define OSSL_ENGINE_LOAD_IF_MATCH(x) \ 00042 do{\ 00043 if(!strcmp(#x, RSTRING_PTR(name))){\ 00044 ENGINE_load_##x();\ 00045 return Qtrue;\ 00046 }\ 00047 }while(0) 00048 00049 static VALUE 00050 ossl_engine_s_load(int argc, VALUE *argv, VALUE klass) 00051 { 00052 #if !defined(HAVE_ENGINE_LOAD_BUILTIN_ENGINES) 00053 return Qnil; 00054 #else 00055 VALUE name; 00056 00057 rb_scan_args(argc, argv, "01", &name); 00058 if(NIL_P(name)){ 00059 ENGINE_load_builtin_engines(); 00060 return Qtrue; 00061 } 00062 StringValue(name); 00063 #ifndef OPENSSL_NO_STATIC_ENGINE 00064 #if HAVE_ENGINE_LOAD_DYNAMIC 00065 OSSL_ENGINE_LOAD_IF_MATCH(dynamic); 00066 #endif 00067 #if HAVE_ENGINE_LOAD_4758CCA 00068 OSSL_ENGINE_LOAD_IF_MATCH(4758cca); 00069 #endif 00070 #if HAVE_ENGINE_LOAD_AEP 00071 OSSL_ENGINE_LOAD_IF_MATCH(aep); 00072 #endif 00073 #if HAVE_ENGINE_LOAD_ATALLA 00074 OSSL_ENGINE_LOAD_IF_MATCH(atalla); 00075 #endif 00076 #if HAVE_ENGINE_LOAD_CHIL 00077 OSSL_ENGINE_LOAD_IF_MATCH(chil); 00078 #endif 00079 #if HAVE_ENGINE_LOAD_CSWIFT 00080 OSSL_ENGINE_LOAD_IF_MATCH(cswift); 00081 #endif 00082 #if HAVE_ENGINE_LOAD_NURON 00083 OSSL_ENGINE_LOAD_IF_MATCH(nuron); 00084 #endif 00085 #if HAVE_ENGINE_LOAD_SUREWARE 00086 OSSL_ENGINE_LOAD_IF_MATCH(sureware); 00087 #endif 00088 #if HAVE_ENGINE_LOAD_UBSEC 00089 OSSL_ENGINE_LOAD_IF_MATCH(ubsec); 00090 #endif 00091 #if HAVE_ENGINE_LOAD_PADLOCK 00092 OSSL_ENGINE_LOAD_IF_MATCH(padlock); 00093 #endif 00094 #if HAVE_ENGINE_LOAD_CAPI 00095 OSSL_ENGINE_LOAD_IF_MATCH(capi); 00096 #endif 00097 #if HAVE_ENGINE_LOAD_GMP 00098 OSSL_ENGINE_LOAD_IF_MATCH(gmp); 00099 #endif 00100 #if HAVE_ENGINE_LOAD_GOST 00101 OSSL_ENGINE_LOAD_IF_MATCH(gost); 00102 #endif 00103 #if HAVE_ENGINE_LOAD_CRYPTODEV 00104 OSSL_ENGINE_LOAD_IF_MATCH(cryptodev); 00105 #endif 00106 #if HAVE_ENGINE_LOAD_AESNI 00107 OSSL_ENGINE_LOAD_IF_MATCH(aesni); 00108 #endif 00109 #endif 00110 #ifdef HAVE_ENGINE_LOAD_OPENBSD_DEV_CRYPTO 00111 OSSL_ENGINE_LOAD_IF_MATCH(openbsd_dev_crypto); 00112 #endif 00113 OSSL_ENGINE_LOAD_IF_MATCH(openssl); 00114 rb_warning("no such builtin loader for `%s'", RSTRING_PTR(name)); 00115 return Qnil; 00116 #endif /* HAVE_ENGINE_LOAD_BUILTIN_ENGINES */ 00117 } 00118 00119 static VALUE 00120 ossl_engine_s_cleanup(VALUE self) 00121 { 00122 #if defined(HAVE_ENGINE_CLEANUP) 00123 ENGINE_cleanup(); 00124 #endif 00125 return Qnil; 00126 } 00127 00128 static VALUE 00129 ossl_engine_s_engines(VALUE klass) 00130 { 00131 ENGINE *e; 00132 VALUE ary, obj; 00133 00134 ary = rb_ary_new(); 00135 for(e = ENGINE_get_first(); e; e = ENGINE_get_next(e)){ 00136 /* Need a ref count of two here because of ENGINE_free being 00137 * called internally by OpenSSL when moving to the next ENGINE 00138 * and by us when releasing the ENGINE reference */ 00139 ENGINE_up_ref(e); 00140 WrapEngine(klass, obj, e); 00141 rb_ary_push(ary, obj); 00142 } 00143 00144 return ary; 00145 } 00146 00147 static VALUE 00148 ossl_engine_s_by_id(VALUE klass, VALUE id) 00149 { 00150 ENGINE *e; 00151 VALUE obj; 00152 00153 StringValue(id); 00154 ossl_engine_s_load(1, &id, klass); 00155 if(!(e = ENGINE_by_id(RSTRING_PTR(id)))) 00156 ossl_raise(eEngineError, NULL); 00157 WrapEngine(klass, obj, e); 00158 if(rb_block_given_p()) rb_yield(obj); 00159 if(!ENGINE_init(e)) 00160 ossl_raise(eEngineError, NULL); 00161 ENGINE_ctrl(e, ENGINE_CTRL_SET_PASSWORD_CALLBACK, 00162 0, NULL, (void(*)(void))ossl_pem_passwd_cb); 00163 ERR_clear_error(); 00164 00165 return obj; 00166 } 00167 00168 static VALUE 00169 ossl_engine_s_alloc(VALUE klass) 00170 { 00171 ENGINE *e; 00172 VALUE obj; 00173 00174 if (!(e = ENGINE_new())) { 00175 ossl_raise(eEngineError, NULL); 00176 } 00177 WrapEngine(klass, obj, e); 00178 00179 return obj; 00180 } 00181 00182 static VALUE 00183 ossl_engine_get_id(VALUE self) 00184 { 00185 ENGINE *e; 00186 GetEngine(self, e); 00187 return rb_str_new2(ENGINE_get_id(e)); 00188 } 00189 00190 static VALUE 00191 ossl_engine_get_name(VALUE self) 00192 { 00193 ENGINE *e; 00194 GetEngine(self, e); 00195 return rb_str_new2(ENGINE_get_name(e)); 00196 } 00197 00198 static VALUE 00199 ossl_engine_finish(VALUE self) 00200 { 00201 ENGINE *e; 00202 00203 GetEngine(self, e); 00204 if(!ENGINE_finish(e)) ossl_raise(eEngineError, NULL); 00205 00206 return Qnil; 00207 } 00208 00209 #if defined(HAVE_ENGINE_GET_CIPHER) 00210 static VALUE 00211 ossl_engine_get_cipher(VALUE self, VALUE name) 00212 { 00213 ENGINE *e; 00214 const EVP_CIPHER *ciph, *tmp; 00215 char *s; 00216 int nid; 00217 00218 s = StringValuePtr(name); 00219 tmp = EVP_get_cipherbyname(s); 00220 if(!tmp) ossl_raise(eEngineError, "no such cipher `%s'", s); 00221 nid = EVP_CIPHER_nid(tmp); 00222 GetEngine(self, e); 00223 ciph = ENGINE_get_cipher(e, nid); 00224 if(!ciph) ossl_raise(eEngineError, NULL); 00225 00226 return ossl_cipher_new(ciph); 00227 } 00228 #else 00229 #define ossl_engine_get_cipher rb_f_notimplement 00230 #endif 00231 00232 #if defined(HAVE_ENGINE_GET_DIGEST) 00233 static VALUE 00234 ossl_engine_get_digest(VALUE self, VALUE name) 00235 { 00236 ENGINE *e; 00237 const EVP_MD *md, *tmp; 00238 char *s; 00239 int nid; 00240 00241 s = StringValuePtr(name); 00242 tmp = EVP_get_digestbyname(s); 00243 if(!tmp) ossl_raise(eEngineError, "no such digest `%s'", s); 00244 nid = EVP_MD_nid(tmp); 00245 GetEngine(self, e); 00246 md = ENGINE_get_digest(e, nid); 00247 if(!md) ossl_raise(eEngineError, NULL); 00248 00249 return ossl_digest_new(md); 00250 } 00251 #else 00252 #define ossl_engine_get_digest rb_f_notimplement 00253 #endif 00254 00255 static VALUE 00256 ossl_engine_load_privkey(int argc, VALUE *argv, VALUE self) 00257 { 00258 ENGINE *e; 00259 EVP_PKEY *pkey; 00260 VALUE id, data, obj; 00261 char *sid, *sdata; 00262 00263 rb_scan_args(argc, argv, "02", &id, &data); 00264 sid = NIL_P(id) ? NULL : StringValuePtr(id); 00265 sdata = NIL_P(data) ? NULL : StringValuePtr(data); 00266 GetEngine(self, e); 00267 #if OPENSSL_VERSION_NUMBER < 0x00907000L 00268 pkey = ENGINE_load_private_key(e, sid, sdata); 00269 #else 00270 pkey = ENGINE_load_private_key(e, sid, NULL, sdata); 00271 #endif 00272 if (!pkey) ossl_raise(eEngineError, NULL); 00273 obj = ossl_pkey_new(pkey); 00274 OSSL_PKEY_SET_PRIVATE(obj); 00275 00276 return obj; 00277 } 00278 00279 static VALUE 00280 ossl_engine_load_pubkey(int argc, VALUE *argv, VALUE self) 00281 { 00282 ENGINE *e; 00283 EVP_PKEY *pkey; 00284 VALUE id, data; 00285 char *sid, *sdata; 00286 00287 rb_scan_args(argc, argv, "02", &id, &data); 00288 sid = NIL_P(id) ? NULL : StringValuePtr(id); 00289 sdata = NIL_P(data) ? NULL : StringValuePtr(data); 00290 GetEngine(self, e); 00291 #if OPENSSL_VERSION_NUMBER < 0x00907000L 00292 pkey = ENGINE_load_public_key(e, sid, sdata); 00293 #else 00294 pkey = ENGINE_load_public_key(e, sid, NULL, sdata); 00295 #endif 00296 if (!pkey) ossl_raise(eEngineError, NULL); 00297 00298 return ossl_pkey_new(pkey); 00299 } 00300 00301 static VALUE 00302 ossl_engine_set_default(VALUE self, VALUE flag) 00303 { 00304 ENGINE *e; 00305 int f = NUM2INT(flag); 00306 00307 GetEngine(self, e); 00308 ENGINE_set_default(e, f); 00309 00310 return Qtrue; 00311 } 00312 00313 static VALUE 00314 ossl_engine_ctrl_cmd(int argc, VALUE *argv, VALUE self) 00315 { 00316 ENGINE *e; 00317 VALUE cmd, val; 00318 int ret; 00319 00320 GetEngine(self, e); 00321 rb_scan_args(argc, argv, "11", &cmd, &val); 00322 StringValue(cmd); 00323 if (!NIL_P(val)) StringValue(val); 00324 ret = ENGINE_ctrl_cmd_string(e, RSTRING_PTR(cmd), 00325 NIL_P(val) ? NULL : RSTRING_PTR(val), 0); 00326 if (!ret) ossl_raise(eEngineError, NULL); 00327 00328 return self; 00329 } 00330 00331 static VALUE 00332 ossl_engine_cmd_flag_to_name(int flag) 00333 { 00334 switch(flag){ 00335 case ENGINE_CMD_FLAG_NUMERIC: return rb_str_new2("NUMERIC"); 00336 case ENGINE_CMD_FLAG_STRING: return rb_str_new2("STRING"); 00337 case ENGINE_CMD_FLAG_NO_INPUT: return rb_str_new2("NO_INPUT"); 00338 case ENGINE_CMD_FLAG_INTERNAL: return rb_str_new2("INTERNAL"); 00339 default: return rb_str_new2("UNKNOWN"); 00340 } 00341 } 00342 00343 static VALUE 00344 ossl_engine_get_cmds(VALUE self) 00345 { 00346 ENGINE *e; 00347 const ENGINE_CMD_DEFN *defn, *p; 00348 VALUE ary, tmp; 00349 00350 GetEngine(self, e); 00351 ary = rb_ary_new(); 00352 if ((defn = ENGINE_get_cmd_defns(e)) != NULL){ 00353 for (p = defn; p->cmd_num > 0; p++){ 00354 tmp = rb_ary_new(); 00355 rb_ary_push(tmp, rb_str_new2(p->cmd_name)); 00356 rb_ary_push(tmp, rb_str_new2(p->cmd_desc)); 00357 rb_ary_push(tmp, ossl_engine_cmd_flag_to_name(p->cmd_flags)); 00358 rb_ary_push(ary, tmp); 00359 } 00360 } 00361 00362 return ary; 00363 } 00364 00365 static VALUE 00366 ossl_engine_inspect(VALUE self) 00367 { 00368 VALUE str; 00369 const char *cname = rb_class2name(rb_obj_class(self)); 00370 00371 str = rb_str_new2("#<"); 00372 rb_str_cat2(str, cname); 00373 rb_str_cat2(str, " id=\""); 00374 rb_str_append(str, ossl_engine_get_id(self)); 00375 rb_str_cat2(str, "\" name=\""); 00376 rb_str_append(str, ossl_engine_get_name(self)); 00377 rb_str_cat2(str, "\">"); 00378 00379 return str; 00380 } 00381 00382 #define DefEngineConst(x) rb_define_const(cEngine, #x, INT2NUM(ENGINE_##x)) 00383 00384 void 00385 Init_ossl_engine() 00386 { 00387 cEngine = rb_define_class_under(mOSSL, "Engine", rb_cObject); 00388 eEngineError = rb_define_class_under(cEngine, "EngineError", eOSSLError); 00389 00390 rb_define_alloc_func(cEngine, ossl_engine_s_alloc); 00391 rb_define_singleton_method(cEngine, "load", ossl_engine_s_load, -1); 00392 rb_define_singleton_method(cEngine, "cleanup", ossl_engine_s_cleanup, 0); 00393 rb_define_singleton_method(cEngine, "engines", ossl_engine_s_engines, 0); 00394 rb_define_singleton_method(cEngine, "by_id", ossl_engine_s_by_id, 1); 00395 rb_undef_method(CLASS_OF(cEngine), "new"); 00396 00397 rb_define_method(cEngine, "id", ossl_engine_get_id, 0); 00398 rb_define_method(cEngine, "name", ossl_engine_get_name, 0); 00399 rb_define_method(cEngine, "finish", ossl_engine_finish, 0); 00400 rb_define_method(cEngine, "cipher", ossl_engine_get_cipher, 1); 00401 rb_define_method(cEngine, "digest", ossl_engine_get_digest, 1); 00402 rb_define_method(cEngine, "load_private_key", ossl_engine_load_privkey, -1); 00403 rb_define_method(cEngine, "load_public_key", ossl_engine_load_pubkey, -1); 00404 rb_define_method(cEngine, "set_default", ossl_engine_set_default, 1); 00405 rb_define_method(cEngine, "ctrl_cmd", ossl_engine_ctrl_cmd, -1); 00406 rb_define_method(cEngine, "cmds", ossl_engine_get_cmds, 0); 00407 rb_define_method(cEngine, "inspect", ossl_engine_inspect, 0); 00408 00409 DefEngineConst(METHOD_RSA); 00410 DefEngineConst(METHOD_DSA); 00411 DefEngineConst(METHOD_DH); 00412 DefEngineConst(METHOD_RAND); 00413 #ifdef ENGINE_METHOD_BN_MOD_EXP 00414 DefEngineConst(METHOD_BN_MOD_EXP); 00415 #endif 00416 #ifdef ENGINE_METHOD_BN_MOD_EXP_CRT 00417 DefEngineConst(METHOD_BN_MOD_EXP_CRT); 00418 #endif 00419 #ifdef ENGINE_METHOD_CIPHERS 00420 DefEngineConst(METHOD_CIPHERS); 00421 #endif 00422 #ifdef ENGINE_METHOD_DIGESTS 00423 DefEngineConst(METHOD_DIGESTS); 00424 #endif 00425 DefEngineConst(METHOD_ALL); 00426 DefEngineConst(METHOD_NONE); 00427 } 00428 #else 00429 void 00430 Init_ossl_engine() 00431 { 00432 } 00433 #endif 00434