• 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 

Generated on Wed Sep 8 2010 21:54:01 for Ruby by  doxygen 1.7.1