|
Ruby 1.9.2p290(2011-07-09revision32553)
|
00001 /* 00002 * $Id: ossl_engine.c 27457 2010-04-23 08:37:55Z usa $ 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_CSWIFT 00068 OSSL_ENGINE_LOAD_IF_MATCH(cswift); 00069 #endif 00070 #if HAVE_ENGINE_LOAD_CHIL 00071 OSSL_ENGINE_LOAD_IF_MATCH(chil); 00072 #endif 00073 #if HAVE_ENGINE_LOAD_ATALLA 00074 OSSL_ENGINE_LOAD_IF_MATCH(atalla); 00075 #endif 00076 #if HAVE_ENGINE_LOAD_NURON 00077 OSSL_ENGINE_LOAD_IF_MATCH(nuron); 00078 #endif 00079 #if HAVE_ENGINE_LOAD_UBSEC 00080 OSSL_ENGINE_LOAD_IF_MATCH(ubsec); 00081 #endif 00082 #if HAVE_ENGINE_LOAD_AEP 00083 OSSL_ENGINE_LOAD_IF_MATCH(aep); 00084 #endif 00085 #if HAVE_ENGINE_LOAD_SUREWARE 00086 OSSL_ENGINE_LOAD_IF_MATCH(sureware); 00087 #endif 00088 #if HAVE_ENGINE_LOAD_4758CCA 00089 OSSL_ENGINE_LOAD_IF_MATCH(4758cca); 00090 #endif 00091 #endif 00092 #ifdef HAVE_ENGINE_LOAD_OPENBSD_DEV_CRYPTO 00093 OSSL_ENGINE_LOAD_IF_MATCH(openbsd_dev_crypto); 00094 #endif 00095 OSSL_ENGINE_LOAD_IF_MATCH(openssl); 00096 rb_warning("no such builtin loader for `%s'", RSTRING_PTR(name)); 00097 return Qnil; 00098 #endif /* HAVE_ENGINE_LOAD_BUILTIN_ENGINES */ 00099 } 00100 00101 static VALUE 00102 ossl_engine_s_cleanup(VALUE self) 00103 { 00104 #if defined(HAVE_ENGINE_CLEANUP) 00105 ENGINE_cleanup(); 00106 #endif 00107 return Qnil; 00108 } 00109 00110 static VALUE 00111 ossl_engine_s_engines(VALUE klass) 00112 { 00113 ENGINE *e; 00114 VALUE ary, obj; 00115 00116 ary = rb_ary_new(); 00117 for(e = ENGINE_get_first(); e; e = ENGINE_get_next(e)){ 00118 WrapEngine(klass, obj, e); 00119 rb_ary_push(ary, obj); 00120 } 00121 00122 return ary; 00123 } 00124 00125 static VALUE 00126 ossl_engine_s_by_id(VALUE klass, VALUE id) 00127 { 00128 ENGINE *e; 00129 VALUE obj; 00130 00131 StringValue(id); 00132 ossl_engine_s_load(1, &id, klass); 00133 if(!(e = ENGINE_by_id(RSTRING_PTR(id)))) 00134 ossl_raise(eEngineError, NULL); 00135 WrapEngine(klass, obj, e); 00136 if(rb_block_given_p()) rb_yield(obj); 00137 if(!ENGINE_init(e)) 00138 ossl_raise(eEngineError, NULL); 00139 ENGINE_ctrl(e, ENGINE_CTRL_SET_PASSWORD_CALLBACK, 00140 0, NULL, (void(*)(void))ossl_pem_passwd_cb); 00141 ERR_clear_error(); 00142 00143 return obj; 00144 } 00145 00146 static VALUE 00147 ossl_engine_s_alloc(VALUE klass) 00148 { 00149 ENGINE *e; 00150 VALUE obj; 00151 00152 if (!(e = ENGINE_new())) { 00153 ossl_raise(eEngineError, NULL); 00154 } 00155 WrapEngine(klass, obj, e); 00156 00157 return obj; 00158 } 00159 00160 static VALUE 00161 ossl_engine_get_id(VALUE self) 00162 { 00163 ENGINE *e; 00164 GetEngine(self, e); 00165 return rb_str_new2(ENGINE_get_id(e)); 00166 } 00167 00168 static VALUE 00169 ossl_engine_get_name(VALUE self) 00170 { 00171 ENGINE *e; 00172 GetEngine(self, e); 00173 return rb_str_new2(ENGINE_get_name(e)); 00174 } 00175 00176 static VALUE 00177 ossl_engine_finish(VALUE self) 00178 { 00179 ENGINE *e; 00180 00181 GetEngine(self, e); 00182 if(!ENGINE_finish(e)) ossl_raise(eEngineError, NULL); 00183 00184 return Qnil; 00185 } 00186 00187 #if defined(HAVE_ENGINE_GET_CIPHER) 00188 static VALUE 00189 ossl_engine_get_cipher(VALUE self, VALUE name) 00190 { 00191 ENGINE *e; 00192 const EVP_CIPHER *ciph, *tmp; 00193 char *s; 00194 int nid; 00195 00196 s = StringValuePtr(name); 00197 tmp = EVP_get_cipherbyname(s); 00198 if(!tmp) ossl_raise(eEngineError, "no such cipher `%s'", s); 00199 nid = EVP_CIPHER_nid(tmp); 00200 GetEngine(self, e); 00201 ciph = ENGINE_get_cipher(e, nid); 00202 if(!ciph) ossl_raise(eEngineError, NULL); 00203 00204 return ossl_cipher_new(ciph); 00205 } 00206 #else 00207 #define ossl_engine_get_cipher rb_f_notimplement 00208 #endif 00209 00210 #if defined(HAVE_ENGINE_GET_DIGEST) 00211 static VALUE 00212 ossl_engine_get_digest(VALUE self, VALUE name) 00213 { 00214 ENGINE *e; 00215 const EVP_MD *md, *tmp; 00216 char *s; 00217 int nid; 00218 00219 s = StringValuePtr(name); 00220 tmp = EVP_get_digestbyname(s); 00221 if(!tmp) ossl_raise(eEngineError, "no such digest `%s'", s); 00222 nid = EVP_MD_nid(tmp); 00223 GetEngine(self, e); 00224 md = ENGINE_get_digest(e, nid); 00225 if(!md) ossl_raise(eEngineError, NULL); 00226 00227 return ossl_digest_new(md); 00228 } 00229 #else 00230 #define ossl_engine_get_digest rb_f_notimplement 00231 #endif 00232 00233 static VALUE 00234 ossl_engine_load_privkey(int argc, VALUE *argv, VALUE self) 00235 { 00236 ENGINE *e; 00237 EVP_PKEY *pkey; 00238 VALUE id, data, obj; 00239 char *sid, *sdata; 00240 00241 rb_scan_args(argc, argv, "02", &id, &data); 00242 sid = NIL_P(id) ? NULL : StringValuePtr(id); 00243 sdata = NIL_P(data) ? NULL : StringValuePtr(data); 00244 GetEngine(self, e); 00245 #if OPENSSL_VERSION_NUMBER < 0x00907000L 00246 pkey = ENGINE_load_private_key(e, sid, sdata); 00247 #else 00248 pkey = ENGINE_load_private_key(e, sid, NULL, sdata); 00249 #endif 00250 if (!pkey) ossl_raise(eEngineError, NULL); 00251 obj = ossl_pkey_new(pkey); 00252 OSSL_PKEY_SET_PRIVATE(obj); 00253 00254 return obj; 00255 } 00256 00257 static VALUE 00258 ossl_engine_load_pubkey(int argc, VALUE *argv, VALUE self) 00259 { 00260 ENGINE *e; 00261 EVP_PKEY *pkey; 00262 VALUE id, data; 00263 char *sid, *sdata; 00264 00265 rb_scan_args(argc, argv, "02", &id, &data); 00266 sid = NIL_P(id) ? NULL : StringValuePtr(id); 00267 sdata = NIL_P(data) ? NULL : StringValuePtr(data); 00268 GetEngine(self, e); 00269 #if OPENSSL_VERSION_NUMBER < 0x00907000L 00270 pkey = ENGINE_load_public_key(e, sid, sdata); 00271 #else 00272 pkey = ENGINE_load_public_key(e, sid, NULL, sdata); 00273 #endif 00274 if (!pkey) ossl_raise(eEngineError, NULL); 00275 00276 return ossl_pkey_new(pkey); 00277 } 00278 00279 static VALUE 00280 ossl_engine_set_default(VALUE self, VALUE flag) 00281 { 00282 ENGINE *e; 00283 int f = NUM2INT(flag); 00284 00285 GetEngine(self, e); 00286 ENGINE_set_default(e, f); 00287 00288 return Qtrue; 00289 } 00290 00291 static VALUE 00292 ossl_engine_ctrl_cmd(int argc, VALUE *argv, VALUE self) 00293 { 00294 ENGINE *e; 00295 VALUE cmd, val; 00296 int ret; 00297 00298 GetEngine(self, e); 00299 rb_scan_args(argc, argv, "11", &cmd, &val); 00300 StringValue(cmd); 00301 if (!NIL_P(val)) StringValue(val); 00302 ret = ENGINE_ctrl_cmd_string(e, RSTRING_PTR(cmd), 00303 NIL_P(val) ? NULL : RSTRING_PTR(val), 0); 00304 if (!ret) ossl_raise(eEngineError, NULL); 00305 00306 return self; 00307 } 00308 00309 static VALUE 00310 ossl_engine_cmd_flag_to_name(int flag) 00311 { 00312 switch(flag){ 00313 case ENGINE_CMD_FLAG_NUMERIC: return rb_str_new2("NUMERIC"); 00314 case ENGINE_CMD_FLAG_STRING: return rb_str_new2("STRING"); 00315 case ENGINE_CMD_FLAG_NO_INPUT: return rb_str_new2("NO_INPUT"); 00316 case ENGINE_CMD_FLAG_INTERNAL: return rb_str_new2("INTERNAL"); 00317 default: return rb_str_new2("UNKNOWN"); 00318 } 00319 } 00320 00321 static VALUE 00322 ossl_engine_get_cmds(VALUE self) 00323 { 00324 ENGINE *e; 00325 const ENGINE_CMD_DEFN *defn, *p; 00326 VALUE ary, tmp; 00327 00328 GetEngine(self, e); 00329 ary = rb_ary_new(); 00330 if ((defn = ENGINE_get_cmd_defns(e)) != NULL){ 00331 for (p = defn; p->cmd_num > 0; p++){ 00332 tmp = rb_ary_new(); 00333 rb_ary_push(tmp, rb_str_new2(p->cmd_name)); 00334 rb_ary_push(tmp, rb_str_new2(p->cmd_desc)); 00335 rb_ary_push(tmp, ossl_engine_cmd_flag_to_name(p->cmd_flags)); 00336 rb_ary_push(ary, tmp); 00337 } 00338 } 00339 00340 return ary; 00341 } 00342 00343 static VALUE 00344 ossl_engine_inspect(VALUE self) 00345 { 00346 VALUE str; 00347 const char *cname = rb_class2name(rb_obj_class(self)); 00348 00349 str = rb_str_new2("#<"); 00350 rb_str_cat2(str, cname); 00351 rb_str_cat2(str, " id=\""); 00352 rb_str_append(str, ossl_engine_get_id(self)); 00353 rb_str_cat2(str, "\" name=\""); 00354 rb_str_append(str, ossl_engine_get_name(self)); 00355 rb_str_cat2(str, "\">"); 00356 00357 return str; 00358 } 00359 00360 #define DefEngineConst(x) rb_define_const(cEngine, #x, INT2NUM(ENGINE_##x)) 00361 00362 void 00363 Init_ossl_engine() 00364 { 00365 cEngine = rb_define_class_under(mOSSL, "Engine", rb_cObject); 00366 eEngineError = rb_define_class_under(cEngine, "EngineError", eOSSLError); 00367 00368 rb_define_alloc_func(cEngine, ossl_engine_s_alloc); 00369 rb_define_singleton_method(cEngine, "load", ossl_engine_s_load, -1); 00370 rb_define_singleton_method(cEngine, "cleanup", ossl_engine_s_cleanup, 0); 00371 rb_define_singleton_method(cEngine, "engines", ossl_engine_s_engines, 0); 00372 rb_define_singleton_method(cEngine, "by_id", ossl_engine_s_by_id, 1); 00373 rb_undef_method(CLASS_OF(cEngine), "new"); 00374 00375 rb_define_method(cEngine, "id", ossl_engine_get_id, 0); 00376 rb_define_method(cEngine, "name", ossl_engine_get_name, 0); 00377 rb_define_method(cEngine, "finish", ossl_engine_finish, 0); 00378 rb_define_method(cEngine, "cipher", ossl_engine_get_cipher, 1); 00379 rb_define_method(cEngine, "digest", ossl_engine_get_digest, 1); 00380 rb_define_method(cEngine, "load_private_key", ossl_engine_load_privkey, -1); 00381 rb_define_method(cEngine, "load_public_key", ossl_engine_load_pubkey, -1); 00382 rb_define_method(cEngine, "set_default", ossl_engine_set_default, 1); 00383 rb_define_method(cEngine, "ctrl_cmd", ossl_engine_ctrl_cmd, -1); 00384 rb_define_method(cEngine, "cmds", ossl_engine_get_cmds, 0); 00385 rb_define_method(cEngine, "inspect", ossl_engine_inspect, 0); 00386 00387 DefEngineConst(METHOD_RSA); 00388 DefEngineConst(METHOD_DSA); 00389 DefEngineConst(METHOD_DH); 00390 DefEngineConst(METHOD_RAND); 00391 #ifdef ENGINE_METHOD_BN_MOD_EXP 00392 DefEngineConst(METHOD_BN_MOD_EXP); 00393 #endif 00394 #ifdef ENGINE_METHOD_BN_MOD_EXP_CRT 00395 DefEngineConst(METHOD_BN_MOD_EXP_CRT); 00396 #endif 00397 #ifdef ENGINE_METHOD_CIPHERS 00398 DefEngineConst(METHOD_CIPHERS); 00399 #endif 00400 #ifdef ENGINE_METHOD_DIGESTS 00401 DefEngineConst(METHOD_DIGESTS); 00402 #endif 00403 DefEngineConst(METHOD_ALL); 00404 DefEngineConst(METHOD_NONE); 00405 } 00406 #else 00407 void 00408 Init_ossl_engine() 00409 { 00410 } 00411 #endif 00412
1.7.3