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
00036
00037
00038
00039
00040
00041
00042 VALUE cEngine;
00043
00044
00045
00046
00047 VALUE eEngineError;
00048
00049
00050
00051
00052 #define OSSL_ENGINE_LOAD_IF_MATCH(x) \
00053 do{\
00054 if(!strcmp(#x, RSTRING_PTR(name))){\
00055 ENGINE_load_##x();\
00056 return Qtrue;\
00057 }\
00058 }while(0)
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071 static VALUE
00072 ossl_engine_s_load(int argc, VALUE *argv, VALUE klass)
00073 {
00074 #if !defined(HAVE_ENGINE_LOAD_BUILTIN_ENGINES)
00075 return Qnil;
00076 #else
00077 VALUE name;
00078
00079 rb_scan_args(argc, argv, "01", &name);
00080 if(NIL_P(name)){
00081 ENGINE_load_builtin_engines();
00082 return Qtrue;
00083 }
00084 StringValue(name);
00085 #ifndef OPENSSL_NO_STATIC_ENGINE
00086 #if HAVE_ENGINE_LOAD_DYNAMIC
00087 OSSL_ENGINE_LOAD_IF_MATCH(dynamic);
00088 #endif
00089 #if HAVE_ENGINE_LOAD_4758CCA
00090 OSSL_ENGINE_LOAD_IF_MATCH(4758cca);
00091 #endif
00092 #if HAVE_ENGINE_LOAD_AEP
00093 OSSL_ENGINE_LOAD_IF_MATCH(aep);
00094 #endif
00095 #if HAVE_ENGINE_LOAD_ATALLA
00096 OSSL_ENGINE_LOAD_IF_MATCH(atalla);
00097 #endif
00098 #if HAVE_ENGINE_LOAD_CHIL
00099 OSSL_ENGINE_LOAD_IF_MATCH(chil);
00100 #endif
00101 #if HAVE_ENGINE_LOAD_CSWIFT
00102 OSSL_ENGINE_LOAD_IF_MATCH(cswift);
00103 #endif
00104 #if HAVE_ENGINE_LOAD_NURON
00105 OSSL_ENGINE_LOAD_IF_MATCH(nuron);
00106 #endif
00107 #if HAVE_ENGINE_LOAD_SUREWARE
00108 OSSL_ENGINE_LOAD_IF_MATCH(sureware);
00109 #endif
00110 #if HAVE_ENGINE_LOAD_UBSEC
00111 OSSL_ENGINE_LOAD_IF_MATCH(ubsec);
00112 #endif
00113 #if HAVE_ENGINE_LOAD_PADLOCK
00114 OSSL_ENGINE_LOAD_IF_MATCH(padlock);
00115 #endif
00116 #if HAVE_ENGINE_LOAD_CAPI
00117 OSSL_ENGINE_LOAD_IF_MATCH(capi);
00118 #endif
00119 #if HAVE_ENGINE_LOAD_GMP
00120 OSSL_ENGINE_LOAD_IF_MATCH(gmp);
00121 #endif
00122 #if HAVE_ENGINE_LOAD_GOST
00123 OSSL_ENGINE_LOAD_IF_MATCH(gost);
00124 #endif
00125 #if HAVE_ENGINE_LOAD_CRYPTODEV
00126 OSSL_ENGINE_LOAD_IF_MATCH(cryptodev);
00127 #endif
00128 #if HAVE_ENGINE_LOAD_AESNI
00129 OSSL_ENGINE_LOAD_IF_MATCH(aesni);
00130 #endif
00131 #endif
00132 #ifdef HAVE_ENGINE_LOAD_OPENBSD_DEV_CRYPTO
00133 OSSL_ENGINE_LOAD_IF_MATCH(openbsd_dev_crypto);
00134 #endif
00135 OSSL_ENGINE_LOAD_IF_MATCH(openssl);
00136 rb_warning("no such builtin loader for `%s'", RSTRING_PTR(name));
00137 return Qnil;
00138 #endif
00139 }
00140
00141
00142
00143
00144
00145
00146
00147
00148
00149
00150 static VALUE
00151 ossl_engine_s_cleanup(VALUE self)
00152 {
00153 #if defined(HAVE_ENGINE_CLEANUP)
00154 ENGINE_cleanup();
00155 #endif
00156 return Qnil;
00157 }
00158
00159
00160
00161
00162
00163 static VALUE
00164 ossl_engine_s_engines(VALUE klass)
00165 {
00166 ENGINE *e;
00167 VALUE ary, obj;
00168
00169 ary = rb_ary_new();
00170 for(e = ENGINE_get_first(); e; e = ENGINE_get_next(e)){
00171
00172
00173
00174 ENGINE_up_ref(e);
00175 WrapEngine(klass, obj, e);
00176 rb_ary_push(ary, obj);
00177 }
00178
00179 return ary;
00180 }
00181
00182
00183
00184
00185
00186
00187
00188
00189
00190
00191
00192
00193
00194 static VALUE
00195 ossl_engine_s_by_id(VALUE klass, VALUE id)
00196 {
00197 ENGINE *e;
00198 VALUE obj;
00199
00200 StringValue(id);
00201 ossl_engine_s_load(1, &id, klass);
00202 if(!(e = ENGINE_by_id(RSTRING_PTR(id))))
00203 ossl_raise(eEngineError, NULL);
00204 WrapEngine(klass, obj, e);
00205 if(rb_block_given_p()) rb_yield(obj);
00206 if(!ENGINE_init(e))
00207 ossl_raise(eEngineError, NULL);
00208 ENGINE_ctrl(e, ENGINE_CTRL_SET_PASSWORD_CALLBACK,
00209 0, NULL, (void(*)(void))ossl_pem_passwd_cb);
00210 ERR_clear_error();
00211
00212 return obj;
00213 }
00214
00215 static VALUE
00216 ossl_engine_s_alloc(VALUE klass)
00217 {
00218 ENGINE *e;
00219 VALUE obj;
00220
00221 if (!(e = ENGINE_new())) {
00222 ossl_raise(eEngineError, NULL);
00223 }
00224 WrapEngine(klass, obj, e);
00225
00226 return obj;
00227 }
00228
00229
00230
00231
00232
00233
00234
00235
00236
00237
00238 static VALUE
00239 ossl_engine_get_id(VALUE self)
00240 {
00241 ENGINE *e;
00242 GetEngine(self, e);
00243 return rb_str_new2(ENGINE_get_id(e));
00244 }
00245
00246
00247
00248
00249
00250
00251
00252
00253
00254
00255
00256 static VALUE
00257 ossl_engine_get_name(VALUE self)
00258 {
00259 ENGINE *e;
00260 GetEngine(self, e);
00261 return rb_str_new2(ENGINE_get_name(e));
00262 }
00263
00264
00265
00266
00267
00268
00269
00270 static VALUE
00271 ossl_engine_finish(VALUE self)
00272 {
00273 ENGINE *e;
00274
00275 GetEngine(self, e);
00276 if(!ENGINE_finish(e)) ossl_raise(eEngineError, NULL);
00277
00278 return Qnil;
00279 }
00280
00281 #if defined(HAVE_ENGINE_GET_CIPHER)
00282
00283
00284
00285
00286
00287
00288
00289
00290
00291
00292
00293
00294
00295
00296
00297
00298 static VALUE
00299 ossl_engine_get_cipher(VALUE self, VALUE name)
00300 {
00301 ENGINE *e;
00302 const EVP_CIPHER *ciph, *tmp;
00303 char *s;
00304 int nid;
00305
00306 s = StringValuePtr(name);
00307 tmp = EVP_get_cipherbyname(s);
00308 if(!tmp) ossl_raise(eEngineError, "no such cipher `%s'", s);
00309 nid = EVP_CIPHER_nid(tmp);
00310 GetEngine(self, e);
00311 ciph = ENGINE_get_cipher(e, nid);
00312 if(!ciph) ossl_raise(eEngineError, NULL);
00313
00314 return ossl_cipher_new(ciph);
00315 }
00316 #else
00317 #define ossl_engine_get_cipher rb_f_notimplement
00318 #endif
00319
00320 #if defined(HAVE_ENGINE_GET_DIGEST)
00321
00322
00323
00324
00325
00326
00327
00328
00329
00330
00331
00332
00333
00334
00335
00336
00337 static VALUE
00338 ossl_engine_get_digest(VALUE self, VALUE name)
00339 {
00340 ENGINE *e;
00341 const EVP_MD *md, *tmp;
00342 char *s;
00343 int nid;
00344
00345 s = StringValuePtr(name);
00346 tmp = EVP_get_digestbyname(s);
00347 if(!tmp) ossl_raise(eEngineError, "no such digest `%s'", s);
00348 nid = EVP_MD_nid(tmp);
00349 GetEngine(self, e);
00350 md = ENGINE_get_digest(e, nid);
00351 if(!md) ossl_raise(eEngineError, NULL);
00352
00353 return ossl_digest_new(md);
00354 }
00355 #else
00356 #define ossl_engine_get_digest rb_f_notimplement
00357 #endif
00358
00359
00360
00361
00362
00363
00364
00365
00366
00367
00368
00369 static VALUE
00370 ossl_engine_load_privkey(int argc, VALUE *argv, VALUE self)
00371 {
00372 ENGINE *e;
00373 EVP_PKEY *pkey;
00374 VALUE id, data, obj;
00375 char *sid, *sdata;
00376
00377 rb_scan_args(argc, argv, "02", &id, &data);
00378 sid = NIL_P(id) ? NULL : StringValuePtr(id);
00379 sdata = NIL_P(data) ? NULL : StringValuePtr(data);
00380 GetEngine(self, e);
00381 #if OPENSSL_VERSION_NUMBER < 0x00907000L
00382 pkey = ENGINE_load_private_key(e, sid, sdata);
00383 #else
00384 pkey = ENGINE_load_private_key(e, sid, NULL, sdata);
00385 #endif
00386 if (!pkey) ossl_raise(eEngineError, NULL);
00387 obj = ossl_pkey_new(pkey);
00388 OSSL_PKEY_SET_PRIVATE(obj);
00389
00390 return obj;
00391 }
00392
00393
00394
00395
00396
00397
00398
00399
00400
00401
00402
00403 static VALUE
00404 ossl_engine_load_pubkey(int argc, VALUE *argv, VALUE self)
00405 {
00406 ENGINE *e;
00407 EVP_PKEY *pkey;
00408 VALUE id, data;
00409 char *sid, *sdata;
00410
00411 rb_scan_args(argc, argv, "02", &id, &data);
00412 sid = NIL_P(id) ? NULL : StringValuePtr(id);
00413 sdata = NIL_P(data) ? NULL : StringValuePtr(data);
00414 GetEngine(self, e);
00415 #if OPENSSL_VERSION_NUMBER < 0x00907000L
00416 pkey = ENGINE_load_public_key(e, sid, sdata);
00417 #else
00418 pkey = ENGINE_load_public_key(e, sid, NULL, sdata);
00419 #endif
00420 if (!pkey) ossl_raise(eEngineError, NULL);
00421
00422 return ossl_pkey_new(pkey);
00423 }
00424
00425
00426
00427
00428
00429
00430
00431
00432
00433
00434
00435
00436
00437
00438
00439
00440
00441
00442 static VALUE
00443 ossl_engine_set_default(VALUE self, VALUE flag)
00444 {
00445 ENGINE *e;
00446 int f = NUM2INT(flag);
00447
00448 GetEngine(self, e);
00449 ENGINE_set_default(e, f);
00450
00451 return Qtrue;
00452 }
00453
00454
00455
00456
00457
00458
00459
00460
00461
00462
00463 static VALUE
00464 ossl_engine_ctrl_cmd(int argc, VALUE *argv, VALUE self)
00465 {
00466 ENGINE *e;
00467 VALUE cmd, val;
00468 int ret;
00469
00470 GetEngine(self, e);
00471 rb_scan_args(argc, argv, "11", &cmd, &val);
00472 StringValue(cmd);
00473 if (!NIL_P(val)) StringValue(val);
00474 ret = ENGINE_ctrl_cmd_string(e, RSTRING_PTR(cmd),
00475 NIL_P(val) ? NULL : RSTRING_PTR(val), 0);
00476 if (!ret) ossl_raise(eEngineError, NULL);
00477
00478 return self;
00479 }
00480
00481 static VALUE
00482 ossl_engine_cmd_flag_to_name(int flag)
00483 {
00484 switch(flag){
00485 case ENGINE_CMD_FLAG_NUMERIC: return rb_str_new2("NUMERIC");
00486 case ENGINE_CMD_FLAG_STRING: return rb_str_new2("STRING");
00487 case ENGINE_CMD_FLAG_NO_INPUT: return rb_str_new2("NO_INPUT");
00488 case ENGINE_CMD_FLAG_INTERNAL: return rb_str_new2("INTERNAL");
00489 default: return rb_str_new2("UNKNOWN");
00490 }
00491 }
00492
00493
00494
00495
00496
00497 static VALUE
00498 ossl_engine_get_cmds(VALUE self)
00499 {
00500 ENGINE *e;
00501 const ENGINE_CMD_DEFN *defn, *p;
00502 VALUE ary, tmp;
00503
00504 GetEngine(self, e);
00505 ary = rb_ary_new();
00506 if ((defn = ENGINE_get_cmd_defns(e)) != NULL){
00507 for (p = defn; p->cmd_num > 0; p++){
00508 tmp = rb_ary_new();
00509 rb_ary_push(tmp, rb_str_new2(p->cmd_name));
00510 rb_ary_push(tmp, rb_str_new2(p->cmd_desc));
00511 rb_ary_push(tmp, ossl_engine_cmd_flag_to_name(p->cmd_flags));
00512 rb_ary_push(ary, tmp);
00513 }
00514 }
00515
00516 return ary;
00517 }
00518
00519
00520
00521
00522
00523 static VALUE
00524 ossl_engine_inspect(VALUE self)
00525 {
00526 VALUE str;
00527 const char *cname = rb_class2name(rb_obj_class(self));
00528
00529 str = rb_str_new2("#<");
00530 rb_str_cat2(str, cname);
00531 rb_str_cat2(str, " id=\"");
00532 rb_str_append(str, ossl_engine_get_id(self));
00533 rb_str_cat2(str, "\" name=\"");
00534 rb_str_append(str, ossl_engine_get_name(self));
00535 rb_str_cat2(str, "\">");
00536
00537 return str;
00538 }
00539
00540 #define DefEngineConst(x) rb_define_const(cEngine, #x, INT2NUM(ENGINE_##x))
00541
00542 void
00543 Init_ossl_engine()
00544 {
00545 cEngine = rb_define_class_under(mOSSL, "Engine", rb_cObject);
00546 eEngineError = rb_define_class_under(cEngine, "EngineError", eOSSLError);
00547
00548 rb_define_alloc_func(cEngine, ossl_engine_s_alloc);
00549 rb_define_singleton_method(cEngine, "load", ossl_engine_s_load, -1);
00550 rb_define_singleton_method(cEngine, "cleanup", ossl_engine_s_cleanup, 0);
00551 rb_define_singleton_method(cEngine, "engines", ossl_engine_s_engines, 0);
00552 rb_define_singleton_method(cEngine, "by_id", ossl_engine_s_by_id, 1);
00553 rb_undef_method(CLASS_OF(cEngine), "new");
00554
00555 rb_define_method(cEngine, "id", ossl_engine_get_id, 0);
00556 rb_define_method(cEngine, "name", ossl_engine_get_name, 0);
00557 rb_define_method(cEngine, "finish", ossl_engine_finish, 0);
00558 rb_define_method(cEngine, "cipher", ossl_engine_get_cipher, 1);
00559 rb_define_method(cEngine, "digest", ossl_engine_get_digest, 1);
00560 rb_define_method(cEngine, "load_private_key", ossl_engine_load_privkey, -1);
00561 rb_define_method(cEngine, "load_public_key", ossl_engine_load_pubkey, -1);
00562 rb_define_method(cEngine, "set_default", ossl_engine_set_default, 1);
00563 rb_define_method(cEngine, "ctrl_cmd", ossl_engine_ctrl_cmd, -1);
00564 rb_define_method(cEngine, "cmds", ossl_engine_get_cmds, 0);
00565 rb_define_method(cEngine, "inspect", ossl_engine_inspect, 0);
00566
00567 DefEngineConst(METHOD_RSA);
00568 DefEngineConst(METHOD_DSA);
00569 DefEngineConst(METHOD_DH);
00570 DefEngineConst(METHOD_RAND);
00571 #ifdef ENGINE_METHOD_BN_MOD_EXP
00572 DefEngineConst(METHOD_BN_MOD_EXP);
00573 #endif
00574 #ifdef ENGINE_METHOD_BN_MOD_EXP_CRT
00575 DefEngineConst(METHOD_BN_MOD_EXP_CRT);
00576 #endif
00577 #ifdef ENGINE_METHOD_CIPHERS
00578 DefEngineConst(METHOD_CIPHERS);
00579 #endif
00580 #ifdef ENGINE_METHOD_DIGESTS
00581 DefEngineConst(METHOD_DIGESTS);
00582 #endif
00583 DefEngineConst(METHOD_ALL);
00584 DefEngineConst(METHOD_NONE);
00585 }
00586 #else
00587 void
00588 Init_ossl_engine()
00589 {
00590 }
00591 #endif
00592