Ruby 1.9.2p136(2010-12-25revision30365)

- Main Page
- Modules
- Data Structures
- Files

- File List
- Globals

# ext/openssl/ossl_engine.c

Go to the documentation of this file.

    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