Ruby 1.9.3p327(2012-11-10revision37606)
|
00001 /* 00002 * $Id: ossl_engine.c 34505 2012-02-09 03:25:07Z 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_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 /* Need a ref count of two here because of ENGINE_free being 00119 * called internally by OpenSSL when moving to the next ENGINE 00120 * and by us when releasing the ENGINE reference */ 00121 ENGINE_up_ref(e); 00122 WrapEngine(klass, obj, e); 00123 rb_ary_push(ary, obj); 00124 } 00125 00126 return ary; 00127 } 00128 00129 static VALUE 00130 ossl_engine_s_by_id(VALUE klass, VALUE id) 00131 { 00132 ENGINE *e; 00133 VALUE obj; 00134 00135 StringValue(id); 00136 ossl_engine_s_load(1, &id, klass); 00137 if(!(e = ENGINE_by_id(RSTRING_PTR(id)))) 00138 ossl_raise(eEngineError, NULL); 00139 WrapEngine(klass, obj, e); 00140 if(rb_block_given_p()) rb_yield(obj); 00141 if(!ENGINE_init(e)) 00142 ossl_raise(eEngineError, NULL); 00143 ENGINE_ctrl(e, ENGINE_CTRL_SET_PASSWORD_CALLBACK, 00144 0, NULL, (void(*)(void))ossl_pem_passwd_cb); 00145 ERR_clear_error(); 00146 00147 return obj; 00148 } 00149 00150 static VALUE 00151 ossl_engine_s_alloc(VALUE klass) 00152 { 00153 ENGINE *e; 00154 VALUE obj; 00155 00156 if (!(e = ENGINE_new())) { 00157 ossl_raise(eEngineError, NULL); 00158 } 00159 WrapEngine(klass, obj, e); 00160 00161 return obj; 00162 } 00163 00164 static VALUE 00165 ossl_engine_get_id(VALUE self) 00166 { 00167 ENGINE *e; 00168 GetEngine(self, e); 00169 return rb_str_new2(ENGINE_get_id(e)); 00170 } 00171 00172 static VALUE 00173 ossl_engine_get_name(VALUE self) 00174 { 00175 ENGINE *e; 00176 GetEngine(self, e); 00177 return rb_str_new2(ENGINE_get_name(e)); 00178 } 00179 00180 static VALUE 00181 ossl_engine_finish(VALUE self) 00182 { 00183 ENGINE *e; 00184 00185 GetEngine(self, e); 00186 if(!ENGINE_finish(e)) ossl_raise(eEngineError, NULL); 00187 00188 return Qnil; 00189 } 00190 00191 #if defined(HAVE_ENGINE_GET_CIPHER) 00192 static VALUE 00193 ossl_engine_get_cipher(VALUE self, VALUE name) 00194 { 00195 ENGINE *e; 00196 const EVP_CIPHER *ciph, *tmp; 00197 char *s; 00198 int nid; 00199 00200 s = StringValuePtr(name); 00201 tmp = EVP_get_cipherbyname(s); 00202 if(!tmp) ossl_raise(eEngineError, "no such cipher `%s'", s); 00203 nid = EVP_CIPHER_nid(tmp); 00204 GetEngine(self, e); 00205 ciph = ENGINE_get_cipher(e, nid); 00206 if(!ciph) ossl_raise(eEngineError, NULL); 00207 00208 return ossl_cipher_new(ciph); 00209 } 00210 #else 00211 #define ossl_engine_get_cipher rb_f_notimplement 00212 #endif 00213 00214 #if defined(HAVE_ENGINE_GET_DIGEST) 00215 static VALUE 00216 ossl_engine_get_digest(VALUE self, VALUE name) 00217 { 00218 ENGINE *e; 00219 const EVP_MD *md, *tmp; 00220 char *s; 00221 int nid; 00222 00223 s = StringValuePtr(name); 00224 tmp = EVP_get_digestbyname(s); 00225 if(!tmp) ossl_raise(eEngineError, "no such digest `%s'", s); 00226 nid = EVP_MD_nid(tmp); 00227 GetEngine(self, e); 00228 md = ENGINE_get_digest(e, nid); 00229 if(!md) ossl_raise(eEngineError, NULL); 00230 00231 return ossl_digest_new(md); 00232 } 00233 #else 00234 #define ossl_engine_get_digest rb_f_notimplement 00235 #endif 00236 00237 static VALUE 00238 ossl_engine_load_privkey(int argc, VALUE *argv, VALUE self) 00239 { 00240 ENGINE *e; 00241 EVP_PKEY *pkey; 00242 VALUE id, data, obj; 00243 char *sid, *sdata; 00244 00245 rb_scan_args(argc, argv, "02", &id, &data); 00246 sid = NIL_P(id) ? NULL : StringValuePtr(id); 00247 sdata = NIL_P(data) ? NULL : StringValuePtr(data); 00248 GetEngine(self, e); 00249 #if OPENSSL_VERSION_NUMBER < 0x00907000L 00250 pkey = ENGINE_load_private_key(e, sid, sdata); 00251 #else 00252 pkey = ENGINE_load_private_key(e, sid, NULL, sdata); 00253 #endif 00254 if (!pkey) ossl_raise(eEngineError, NULL); 00255 obj = ossl_pkey_new(pkey); 00256 OSSL_PKEY_SET_PRIVATE(obj); 00257 00258 return obj; 00259 } 00260 00261 static VALUE 00262 ossl_engine_load_pubkey(int argc, VALUE *argv, VALUE self) 00263 { 00264 ENGINE *e; 00265 EVP_PKEY *pkey; 00266 VALUE id, data; 00267 char *sid, *sdata; 00268 00269 rb_scan_args(argc, argv, "02", &id, &data); 00270 sid = NIL_P(id) ? NULL : StringValuePtr(id); 00271 sdata = NIL_P(data) ? NULL : StringValuePtr(data); 00272 GetEngine(self, e); 00273 #if OPENSSL_VERSION_NUMBER < 0x00907000L 00274 pkey = ENGINE_load_public_key(e, sid, sdata); 00275 #else 00276 pkey = ENGINE_load_public_key(e, sid, NULL, sdata); 00277 #endif 00278 if (!pkey) ossl_raise(eEngineError, NULL); 00279 00280 return ossl_pkey_new(pkey); 00281 } 00282 00283 static VALUE 00284 ossl_engine_set_default(VALUE self, VALUE flag) 00285 { 00286 ENGINE *e; 00287 int f = NUM2INT(flag); 00288 00289 GetEngine(self, e); 00290 ENGINE_set_default(e, f); 00291 00292 return Qtrue; 00293 } 00294 00295 static VALUE 00296 ossl_engine_ctrl_cmd(int argc, VALUE *argv, VALUE self) 00297 { 00298 ENGINE *e; 00299 VALUE cmd, val; 00300 int ret; 00301 00302 GetEngine(self, e); 00303 rb_scan_args(argc, argv, "11", &cmd, &val); 00304 StringValue(cmd); 00305 if (!NIL_P(val)) StringValue(val); 00306 ret = ENGINE_ctrl_cmd_string(e, RSTRING_PTR(cmd), 00307 NIL_P(val) ? NULL : RSTRING_PTR(val), 0); 00308 if (!ret) ossl_raise(eEngineError, NULL); 00309 00310 return self; 00311 } 00312 00313 static VALUE 00314 ossl_engine_cmd_flag_to_name(int flag) 00315 { 00316 switch(flag){ 00317 case ENGINE_CMD_FLAG_NUMERIC: return rb_str_new2("NUMERIC"); 00318 case ENGINE_CMD_FLAG_STRING: return rb_str_new2("STRING"); 00319 case ENGINE_CMD_FLAG_NO_INPUT: return rb_str_new2("NO_INPUT"); 00320 case ENGINE_CMD_FLAG_INTERNAL: return rb_str_new2("INTERNAL"); 00321 default: return rb_str_new2("UNKNOWN"); 00322 } 00323 } 00324 00325 static VALUE 00326 ossl_engine_get_cmds(VALUE self) 00327 { 00328 ENGINE *e; 00329 const ENGINE_CMD_DEFN *defn, *p; 00330 VALUE ary, tmp; 00331 00332 GetEngine(self, e); 00333 ary = rb_ary_new(); 00334 if ((defn = ENGINE_get_cmd_defns(e)) != NULL){ 00335 for (p = defn; p->cmd_num > 0; p++){ 00336 tmp = rb_ary_new(); 00337 rb_ary_push(tmp, rb_str_new2(p->cmd_name)); 00338 rb_ary_push(tmp, rb_str_new2(p->cmd_desc)); 00339 rb_ary_push(tmp, ossl_engine_cmd_flag_to_name(p->cmd_flags)); 00340 rb_ary_push(ary, tmp); 00341 } 00342 } 00343 00344 return ary; 00345 } 00346 00347 static VALUE 00348 ossl_engine_inspect(VALUE self) 00349 { 00350 VALUE str; 00351 const char *cname = rb_class2name(rb_obj_class(self)); 00352 00353 str = rb_str_new2("#<"); 00354 rb_str_cat2(str, cname); 00355 rb_str_cat2(str, " id=\""); 00356 rb_str_append(str, ossl_engine_get_id(self)); 00357 rb_str_cat2(str, "\" name=\""); 00358 rb_str_append(str, ossl_engine_get_name(self)); 00359 rb_str_cat2(str, "\">"); 00360 00361 return str; 00362 } 00363 00364 #define DefEngineConst(x) rb_define_const(cEngine, #x, INT2NUM(ENGINE_##x)) 00365 00366 void 00367 Init_ossl_engine() 00368 { 00369 cEngine = rb_define_class_under(mOSSL, "Engine", rb_cObject); 00370 eEngineError = rb_define_class_under(cEngine, "EngineError", eOSSLError); 00371 00372 rb_define_alloc_func(cEngine, ossl_engine_s_alloc); 00373 rb_define_singleton_method(cEngine, "load", ossl_engine_s_load, -1); 00374 rb_define_singleton_method(cEngine, "cleanup", ossl_engine_s_cleanup, 0); 00375 rb_define_singleton_method(cEngine, "engines", ossl_engine_s_engines, 0); 00376 rb_define_singleton_method(cEngine, "by_id", ossl_engine_s_by_id, 1); 00377 rb_undef_method(CLASS_OF(cEngine), "new"); 00378 00379 rb_define_method(cEngine, "id", ossl_engine_get_id, 0); 00380 rb_define_method(cEngine, "name", ossl_engine_get_name, 0); 00381 rb_define_method(cEngine, "finish", ossl_engine_finish, 0); 00382 rb_define_method(cEngine, "cipher", ossl_engine_get_cipher, 1); 00383 rb_define_method(cEngine, "digest", ossl_engine_get_digest, 1); 00384 rb_define_method(cEngine, "load_private_key", ossl_engine_load_privkey, -1); 00385 rb_define_method(cEngine, "load_public_key", ossl_engine_load_pubkey, -1); 00386 rb_define_method(cEngine, "set_default", ossl_engine_set_default, 1); 00387 rb_define_method(cEngine, "ctrl_cmd", ossl_engine_ctrl_cmd, -1); 00388 rb_define_method(cEngine, "cmds", ossl_engine_get_cmds, 0); 00389 rb_define_method(cEngine, "inspect", ossl_engine_inspect, 0); 00390 00391 DefEngineConst(METHOD_RSA); 00392 DefEngineConst(METHOD_DSA); 00393 DefEngineConst(METHOD_DH); 00394 DefEngineConst(METHOD_RAND); 00395 #ifdef ENGINE_METHOD_BN_MOD_EXP 00396 DefEngineConst(METHOD_BN_MOD_EXP); 00397 #endif 00398 #ifdef ENGINE_METHOD_BN_MOD_EXP_CRT 00399 DefEngineConst(METHOD_BN_MOD_EXP_CRT); 00400 #endif 00401 #ifdef ENGINE_METHOD_CIPHERS 00402 DefEngineConst(METHOD_CIPHERS); 00403 #endif 00404 #ifdef ENGINE_METHOD_DIGESTS 00405 DefEngineConst(METHOD_DIGESTS); 00406 #endif 00407 DefEngineConst(METHOD_ALL); 00408 DefEngineConst(METHOD_NONE); 00409 } 00410 #else 00411 void 00412 Init_ossl_engine() 00413 { 00414 } 00415 #endif 00416