Ruby  2.0.0p451(2014-02-24revision45167)
ossl_engine.c
Go to the documentation of this file.
1 /*
2  * $Id: ossl_engine.c 44659 2014-01-19 16:28:53Z nagachika $
3  * 'OpenSSL for Ruby' project
4  * Copyright (C) 2003 GOTOU Yuuzou <gotoyuzo@notwork.org>
5  * All rights reserved.
6  */
7 /*
8  * This program is licenced under the same licence as Ruby.
9  * (See the file 'LICENCE'.)
10  */
11 #include "ossl.h"
12 
13 #if defined(OSSL_ENGINE_ENABLED)
14 
15 #define WrapEngine(klass, obj, engine) do { \
16  if (!(engine)) { \
17  ossl_raise(rb_eRuntimeError, "ENGINE wasn't initialized."); \
18  } \
19  (obj) = Data_Wrap_Struct((klass), 0, ENGINE_free, (engine)); \
20 } while(0)
21 #define GetEngine(obj, engine) do { \
22  Data_Get_Struct((obj), ENGINE, (engine)); \
23  if (!(engine)) { \
24  ossl_raise(rb_eRuntimeError, "ENGINE wasn't initialized."); \
25  } \
26 } while (0)
27 #define SafeGetEngine(obj, engine) do { \
28  OSSL_Check_Kind((obj), cEngine); \
29  GetPKCS7((obj), (engine)); \
30 } while (0)
31 
32 /*
33  * Classes
34  */
37 
38 /*
39  * Private
40  */
41 #define OSSL_ENGINE_LOAD_IF_MATCH(x) \
42 do{\
43  if(!strcmp(#x, RSTRING_PTR(name))){\
44  ENGINE_load_##x();\
45  return Qtrue;\
46  }\
47 }while(0)
48 
49 static VALUE
50 ossl_engine_s_load(int argc, VALUE *argv, VALUE klass)
51 {
52 #if !defined(HAVE_ENGINE_LOAD_BUILTIN_ENGINES)
53  return Qnil;
54 #else
55  VALUE name;
56 
57  rb_scan_args(argc, argv, "01", &name);
58  if(NIL_P(name)){
59  ENGINE_load_builtin_engines();
60  return Qtrue;
61  }
62  StringValue(name);
63 #ifndef OPENSSL_NO_STATIC_ENGINE
64 #if HAVE_ENGINE_LOAD_DYNAMIC
65  OSSL_ENGINE_LOAD_IF_MATCH(dynamic);
66 #endif
67 #if HAVE_ENGINE_LOAD_4758CCA
68  OSSL_ENGINE_LOAD_IF_MATCH(4758cca);
69 #endif
70 #if HAVE_ENGINE_LOAD_AEP
71  OSSL_ENGINE_LOAD_IF_MATCH(aep);
72 #endif
73 #if HAVE_ENGINE_LOAD_ATALLA
74  OSSL_ENGINE_LOAD_IF_MATCH(atalla);
75 #endif
76 #if HAVE_ENGINE_LOAD_CHIL
77  OSSL_ENGINE_LOAD_IF_MATCH(chil);
78 #endif
79 #if HAVE_ENGINE_LOAD_CSWIFT
80  OSSL_ENGINE_LOAD_IF_MATCH(cswift);
81 #endif
82 #if HAVE_ENGINE_LOAD_NURON
83  OSSL_ENGINE_LOAD_IF_MATCH(nuron);
84 #endif
85 #if HAVE_ENGINE_LOAD_SUREWARE
86  OSSL_ENGINE_LOAD_IF_MATCH(sureware);
87 #endif
88 #if HAVE_ENGINE_LOAD_UBSEC
89  OSSL_ENGINE_LOAD_IF_MATCH(ubsec);
90 #endif
91 #if HAVE_ENGINE_LOAD_PADLOCK
92  OSSL_ENGINE_LOAD_IF_MATCH(padlock);
93 #endif
94 #if HAVE_ENGINE_LOAD_CAPI
95  OSSL_ENGINE_LOAD_IF_MATCH(capi);
96 #endif
97 #if HAVE_ENGINE_LOAD_GMP
98  OSSL_ENGINE_LOAD_IF_MATCH(gmp);
99 #endif
100 #if HAVE_ENGINE_LOAD_GOST
101  OSSL_ENGINE_LOAD_IF_MATCH(gost);
102 #endif
103 #if HAVE_ENGINE_LOAD_CRYPTODEV
104  OSSL_ENGINE_LOAD_IF_MATCH(cryptodev);
105 #endif
106 #if HAVE_ENGINE_LOAD_AESNI
107  OSSL_ENGINE_LOAD_IF_MATCH(aesni);
108 #endif
109 #endif
110 #ifdef HAVE_ENGINE_LOAD_OPENBSD_DEV_CRYPTO
111  OSSL_ENGINE_LOAD_IF_MATCH(openbsd_dev_crypto);
112 #endif
113  OSSL_ENGINE_LOAD_IF_MATCH(openssl);
114  rb_warning("no such builtin loader for `%s'", RSTRING_PTR(name));
115  return Qnil;
116 #endif /* HAVE_ENGINE_LOAD_BUILTIN_ENGINES */
117 }
118 
119 static VALUE
120 ossl_engine_s_cleanup(VALUE self)
121 {
122 #if defined(HAVE_ENGINE_CLEANUP)
123  ENGINE_cleanup();
124 #endif
125  return Qnil;
126 }
127 
128 static VALUE
129 ossl_engine_s_engines(VALUE klass)
130 {
131  ENGINE *e;
132  VALUE ary, obj;
133 
134  ary = rb_ary_new();
135  for(e = ENGINE_get_first(); e; e = ENGINE_get_next(e)){
136  /* Need a ref count of two here because of ENGINE_free being
137  * called internally by OpenSSL when moving to the next ENGINE
138  * and by us when releasing the ENGINE reference */
139  ENGINE_up_ref(e);
140  WrapEngine(klass, obj, e);
141  rb_ary_push(ary, obj);
142  }
143 
144  return ary;
145 }
146 
147 static VALUE
148 ossl_engine_s_by_id(VALUE klass, VALUE id)
149 {
150  ENGINE *e;
151  VALUE obj;
152 
153  StringValue(id);
154  ossl_engine_s_load(1, &id, klass);
155  if(!(e = ENGINE_by_id(RSTRING_PTR(id))))
157  WrapEngine(klass, obj, e);
158  if(rb_block_given_p()) rb_yield(obj);
159  if(!ENGINE_init(e))
161  ENGINE_ctrl(e, ENGINE_CTRL_SET_PASSWORD_CALLBACK,
162  0, NULL, (void(*)(void))ossl_pem_passwd_cb);
163  ERR_clear_error();
164 
165  return obj;
166 }
167 
168 static VALUE
169 ossl_engine_s_alloc(VALUE klass)
170 {
171  ENGINE *e;
172  VALUE obj;
173 
174  if (!(e = ENGINE_new())) {
176  }
177  WrapEngine(klass, obj, e);
178 
179  return obj;
180 }
181 
182 static VALUE
183 ossl_engine_get_id(VALUE self)
184 {
185  ENGINE *e;
186  GetEngine(self, e);
187  return rb_str_new2(ENGINE_get_id(e));
188 }
189 
190 static VALUE
191 ossl_engine_get_name(VALUE self)
192 {
193  ENGINE *e;
194  GetEngine(self, e);
195  return rb_str_new2(ENGINE_get_name(e));
196 }
197 
198 static VALUE
199 ossl_engine_finish(VALUE self)
200 {
201  ENGINE *e;
202 
203  GetEngine(self, e);
204  if(!ENGINE_finish(e)) ossl_raise(eEngineError, NULL);
205 
206  return Qnil;
207 }
208 
209 #if defined(HAVE_ENGINE_GET_CIPHER)
210 static VALUE
211 ossl_engine_get_cipher(VALUE self, VALUE name)
212 {
213  ENGINE *e;
214  const EVP_CIPHER *ciph, *tmp;
215  char *s;
216  int nid;
217 
218  s = StringValuePtr(name);
219  tmp = EVP_get_cipherbyname(s);
220  if(!tmp) ossl_raise(eEngineError, "no such cipher `%s'", s);
221  nid = EVP_CIPHER_nid(tmp);
222  GetEngine(self, e);
223  ciph = ENGINE_get_cipher(e, nid);
224  if(!ciph) ossl_raise(eEngineError, NULL);
225 
226  return ossl_cipher_new(ciph);
227 }
228 #else
229 #define ossl_engine_get_cipher rb_f_notimplement
230 #endif
231 
232 #if defined(HAVE_ENGINE_GET_DIGEST)
233 static VALUE
234 ossl_engine_get_digest(VALUE self, VALUE name)
235 {
236  ENGINE *e;
237  const EVP_MD *md, *tmp;
238  char *s;
239  int nid;
240 
241  s = StringValuePtr(name);
242  tmp = EVP_get_digestbyname(s);
243  if(!tmp) ossl_raise(eEngineError, "no such digest `%s'", s);
244  nid = EVP_MD_nid(tmp);
245  GetEngine(self, e);
246  md = ENGINE_get_digest(e, nid);
247  if(!md) ossl_raise(eEngineError, NULL);
248 
249  return ossl_digest_new(md);
250 }
251 #else
252 #define ossl_engine_get_digest rb_f_notimplement
253 #endif
254 
255 static VALUE
256 ossl_engine_load_privkey(int argc, VALUE *argv, VALUE self)
257 {
258  ENGINE *e;
259  EVP_PKEY *pkey;
260  VALUE id, data, obj;
261  char *sid, *sdata;
262 
263  rb_scan_args(argc, argv, "02", &id, &data);
264  sid = NIL_P(id) ? NULL : StringValuePtr(id);
265  sdata = NIL_P(data) ? NULL : StringValuePtr(data);
266  GetEngine(self, e);
267 #if OPENSSL_VERSION_NUMBER < 0x00907000L
268  pkey = ENGINE_load_private_key(e, sid, sdata);
269 #else
270  pkey = ENGINE_load_private_key(e, sid, NULL, sdata);
271 #endif
272  if (!pkey) ossl_raise(eEngineError, NULL);
273  obj = ossl_pkey_new(pkey);
275 
276  return obj;
277 }
278 
279 static VALUE
280 ossl_engine_load_pubkey(int argc, VALUE *argv, VALUE self)
281 {
282  ENGINE *e;
283  EVP_PKEY *pkey;
284  VALUE id, data;
285  char *sid, *sdata;
286 
287  rb_scan_args(argc, argv, "02", &id, &data);
288  sid = NIL_P(id) ? NULL : StringValuePtr(id);
289  sdata = NIL_P(data) ? NULL : StringValuePtr(data);
290  GetEngine(self, e);
291 #if OPENSSL_VERSION_NUMBER < 0x00907000L
292  pkey = ENGINE_load_public_key(e, sid, sdata);
293 #else
294  pkey = ENGINE_load_public_key(e, sid, NULL, sdata);
295 #endif
296  if (!pkey) ossl_raise(eEngineError, NULL);
297 
298  return ossl_pkey_new(pkey);
299 }
300 
301 static VALUE
302 ossl_engine_set_default(VALUE self, VALUE flag)
303 {
304  ENGINE *e;
305  int f = NUM2INT(flag);
306 
307  GetEngine(self, e);
308  ENGINE_set_default(e, f);
309 
310  return Qtrue;
311 }
312 
313 static VALUE
314 ossl_engine_ctrl_cmd(int argc, VALUE *argv, VALUE self)
315 {
316  ENGINE *e;
317  VALUE cmd, val;
318  int ret;
319 
320  GetEngine(self, e);
321  rb_scan_args(argc, argv, "11", &cmd, &val);
322  StringValue(cmd);
323  if (!NIL_P(val)) StringValue(val);
324  ret = ENGINE_ctrl_cmd_string(e, RSTRING_PTR(cmd),
325  NIL_P(val) ? NULL : RSTRING_PTR(val), 0);
326  if (!ret) ossl_raise(eEngineError, NULL);
327 
328  return self;
329 }
330 
331 static VALUE
332 ossl_engine_cmd_flag_to_name(int flag)
333 {
334  switch(flag){
335  case ENGINE_CMD_FLAG_NUMERIC: return rb_str_new2("NUMERIC");
336  case ENGINE_CMD_FLAG_STRING: return rb_str_new2("STRING");
337  case ENGINE_CMD_FLAG_NO_INPUT: return rb_str_new2("NO_INPUT");
338  case ENGINE_CMD_FLAG_INTERNAL: return rb_str_new2("INTERNAL");
339  default: return rb_str_new2("UNKNOWN");
340  }
341 }
342 
343 static VALUE
344 ossl_engine_get_cmds(VALUE self)
345 {
346  ENGINE *e;
347  const ENGINE_CMD_DEFN *defn, *p;
348  VALUE ary, tmp;
349 
350  GetEngine(self, e);
351  ary = rb_ary_new();
352  if ((defn = ENGINE_get_cmd_defns(e)) != NULL){
353  for (p = defn; p->cmd_num > 0; p++){
354  tmp = rb_ary_new();
355  rb_ary_push(tmp, rb_str_new2(p->cmd_name));
356  rb_ary_push(tmp, rb_str_new2(p->cmd_desc));
357  rb_ary_push(tmp, ossl_engine_cmd_flag_to_name(p->cmd_flags));
358  rb_ary_push(ary, tmp);
359  }
360  }
361 
362  return ary;
363 }
364 
365 static VALUE
366 ossl_engine_inspect(VALUE self)
367 {
368  ENGINE *e;
369 
370  GetEngine(self, e);
371  return rb_sprintf("#<%"PRIsVALUE" id=\"%s\" name=\"%s\">",
372  rb_obj_class(self), ENGINE_get_id(e), ENGINE_get_name(e));
373 }
374 
375 #define DefEngineConst(x) rb_define_const(cEngine, #x, INT2NUM(ENGINE_##x))
376 
377 void
379 {
382 
383  rb_define_alloc_func(cEngine, ossl_engine_s_alloc);
384  rb_define_singleton_method(cEngine, "load", ossl_engine_s_load, -1);
385  rb_define_singleton_method(cEngine, "cleanup", ossl_engine_s_cleanup, 0);
386  rb_define_singleton_method(cEngine, "engines", ossl_engine_s_engines, 0);
387  rb_define_singleton_method(cEngine, "by_id", ossl_engine_s_by_id, 1);
389 
390  rb_define_method(cEngine, "id", ossl_engine_get_id, 0);
391  rb_define_method(cEngine, "name", ossl_engine_get_name, 0);
392  rb_define_method(cEngine, "finish", ossl_engine_finish, 0);
393  rb_define_method(cEngine, "cipher", ossl_engine_get_cipher, 1);
394  rb_define_method(cEngine, "digest", ossl_engine_get_digest, 1);
395  rb_define_method(cEngine, "load_private_key", ossl_engine_load_privkey, -1);
396  rb_define_method(cEngine, "load_public_key", ossl_engine_load_pubkey, -1);
397  rb_define_method(cEngine, "set_default", ossl_engine_set_default, 1);
398  rb_define_method(cEngine, "ctrl_cmd", ossl_engine_ctrl_cmd, -1);
399  rb_define_method(cEngine, "cmds", ossl_engine_get_cmds, 0);
400  rb_define_method(cEngine, "inspect", ossl_engine_inspect, 0);
401 
402  DefEngineConst(METHOD_RSA);
403  DefEngineConst(METHOD_DSA);
404  DefEngineConst(METHOD_DH);
405  DefEngineConst(METHOD_RAND);
406 #ifdef ENGINE_METHOD_BN_MOD_EXP
407  DefEngineConst(METHOD_BN_MOD_EXP);
408 #endif
409 #ifdef ENGINE_METHOD_BN_MOD_EXP_CRT
410  DefEngineConst(METHOD_BN_MOD_EXP_CRT);
411 #endif
412 #ifdef ENGINE_METHOD_CIPHERS
413  DefEngineConst(METHOD_CIPHERS);
414 #endif
415 #ifdef ENGINE_METHOD_DIGESTS
416  DefEngineConst(METHOD_DIGESTS);
417 #endif
418  DefEngineConst(METHOD_ALL);
419  DefEngineConst(METHOD_NONE);
420 }
421 #else
422 void
424 {
425 }
426 #endif
VALUE mOSSL
Definition: ossl.c:259
unsigned long VALUE
Definition: ripper.y:104
void rb_define_singleton_method(VALUE obj, const char *name, VALUE(*func)(ANYARGS), int argc)
Defines a singleton method for obj.
Definition: class.c:1497
const int id
Definition: nkf.c:209
void rb_define_alloc_func(VALUE, rb_alloc_func_t)
VALUE eEngineError
VALUE rb_ary_push(VALUE ary, VALUE item)
Definition: array.c:822
#define RSTRING_PTR(str)
#define CLASS_OF(v)
#define Qnil
VALUE rb_define_class_under(VALUE outer, const char *name, VALUE super)
Defines a class under the namespace of outer.
Definition: class.c:545
VALUE rb_obj_class(VALUE)
Definition: object.c:194
#define rb_str_new2
VALUE ossl_pkey_new(EVP_PKEY *pkey)
Definition: ossl_pkey.c:76
void rb_undef_method(VALUE klass, const char *name)
Definition: class.c:1362
Win32OLEIDispatch * p
Definition: win32ole.c:786
VALUE cEngine
VALUE ossl_cipher_new(const EVP_CIPHER *cipher)
Definition: ossl_cipher.c:55
#define OSSL_PKEY_SET_PRIVATE(obj)
Definition: ossl_pkey.h:19
int rb_block_given_p(void)
Definition: eval.c:672
#define StringValuePtr(v)
#define val
#define Qtrue
VALUE rb_ary_new(void)
Definition: array.c:424
VALUE ossl_digest_new(const EVP_MD *md)
Definition: ossl_digest.c:64
VALUE eOSSLError
Definition: ossl.c:264
int argc
Definition: ruby.c:130
#define NIL_P(v)
void Init_ossl_engine()
Definition: ossl_engine.c:423
VALUE rb_yield(VALUE)
Definition: vm_eval.c:933
VALUE rb_sprintf(const char *format,...)
Definition: sprintf.c:1270
#define StringValue(v)
int rb_scan_args(int argc, const VALUE *argv, const char *fmt,...)
Definition: class.c:1570
#define f
RUBY_EXTERN VALUE rb_cObject
Definition: ripper.y:1426
void ossl_raise(VALUE exc, const char *fmt,...)
Definition: ossl.c:332
const char * name
Definition: nkf.c:208
#define NUM2INT(x)
#define PRIsVALUE
int ossl_pem_passwd_cb(char *buf, int max_len, int flag, void *pwd)
Definition: ossl.c:162
void rb_warning(const char *fmt,...)
Definition: error.c:229
#define NULL
Definition: _sdbm.c:103
void rb_define_method(VALUE klass, const char *name, VALUE(*func)(ANYARGS), int argc)
Definition: class.c:1344
char ** argv
Definition: ruby.c:131