00001
00002
00003
00004
00005
00006
00007
00008
00009
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
00034
00035 VALUE cEngine;
00036 VALUE eEngineError;
00037
00038
00039
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
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
00137
00138
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 ENGINE *e;
00369
00370 GetEngine(self, e);
00371 return rb_sprintf("#<%"PRIsVALUE" id=\"%s\" name=\"%s\">",
00372 rb_obj_class(self), ENGINE_get_id(e), ENGINE_get_name(e));
00373 }
00374
00375 #define DefEngineConst(x) rb_define_const(cEngine, #x, INT2NUM(ENGINE_##x))
00376
00377 void
00378 Init_ossl_engine()
00379 {
00380 cEngine = rb_define_class_under(mOSSL, "Engine", rb_cObject);
00381 eEngineError = rb_define_class_under(cEngine, "EngineError", eOSSLError);
00382
00383 rb_define_alloc_func(cEngine, ossl_engine_s_alloc);
00384 rb_define_singleton_method(cEngine, "load", ossl_engine_s_load, -1);
00385 rb_define_singleton_method(cEngine, "cleanup", ossl_engine_s_cleanup, 0);
00386 rb_define_singleton_method(cEngine, "engines", ossl_engine_s_engines, 0);
00387 rb_define_singleton_method(cEngine, "by_id", ossl_engine_s_by_id, 1);
00388 rb_undef_method(CLASS_OF(cEngine), "new");
00389
00390 rb_define_method(cEngine, "id", ossl_engine_get_id, 0);
00391 rb_define_method(cEngine, "name", ossl_engine_get_name, 0);
00392 rb_define_method(cEngine, "finish", ossl_engine_finish, 0);
00393 rb_define_method(cEngine, "cipher", ossl_engine_get_cipher, 1);
00394 rb_define_method(cEngine, "digest", ossl_engine_get_digest, 1);
00395 rb_define_method(cEngine, "load_private_key", ossl_engine_load_privkey, -1);
00396 rb_define_method(cEngine, "load_public_key", ossl_engine_load_pubkey, -1);
00397 rb_define_method(cEngine, "set_default", ossl_engine_set_default, 1);
00398 rb_define_method(cEngine, "ctrl_cmd", ossl_engine_ctrl_cmd, -1);
00399 rb_define_method(cEngine, "cmds", ossl_engine_get_cmds, 0);
00400 rb_define_method(cEngine, "inspect", ossl_engine_inspect, 0);
00401
00402 DefEngineConst(METHOD_RSA);
00403 DefEngineConst(METHOD_DSA);
00404 DefEngineConst(METHOD_DH);
00405 DefEngineConst(METHOD_RAND);
00406 #ifdef ENGINE_METHOD_BN_MOD_EXP
00407 DefEngineConst(METHOD_BN_MOD_EXP);
00408 #endif
00409 #ifdef ENGINE_METHOD_BN_MOD_EXP_CRT
00410 DefEngineConst(METHOD_BN_MOD_EXP_CRT);
00411 #endif
00412 #ifdef ENGINE_METHOD_CIPHERS
00413 DefEngineConst(METHOD_CIPHERS);
00414 #endif
00415 #ifdef ENGINE_METHOD_DIGESTS
00416 DefEngineConst(METHOD_DIGESTS);
00417 #endif
00418 DefEngineConst(METHOD_ALL);
00419 DefEngineConst(METHOD_NONE);
00420 }
00421 #else
00422 void
00423 Init_ossl_engine()
00424 {
00425 }
00426 #endif
00427