Ruby  2.4.2p198(2017-09-14revision59899)
ossl_engine.c
Go to the documentation of this file.
1 /*
2  * 'OpenSSL for Ruby' project
3  * Copyright (C) 2003 GOTOU Yuuzou <gotoyuzo@notwork.org>
4  * All rights reserved.
5  */
6 /*
7  * This program is licensed under the same licence as Ruby.
8  * (See the file 'LICENCE'.)
9  */
10 #include "ossl.h"
11 
12 #if !defined(OPENSSL_NO_ENGINE)
13 
14 #define NewEngine(klass) \
15  TypedData_Wrap_Struct((klass), &ossl_engine_type, 0)
16 #define SetEngine(obj, engine) do { \
17  if (!(engine)) { \
18  ossl_raise(rb_eRuntimeError, "ENGINE wasn't initialized."); \
19  } \
20  RTYPEDDATA_DATA(obj) = (engine); \
21 } while(0)
22 #define GetEngine(obj, engine) do { \
23  TypedData_Get_Struct((obj), ENGINE, &ossl_engine_type, (engine)); \
24  if (!(engine)) { \
25  ossl_raise(rb_eRuntimeError, "ENGINE wasn't initialized."); \
26  } \
27 } while (0)
28 #define SafeGetEngine(obj, engine) do { \
29  OSSL_Check_Kind((obj), cEngine); \
30  GetPKCS7((obj), (engine)); \
31 } while (0)
32 
33 /*
34  * Classes
35  */
36 /* Document-class: OpenSSL::Engine
37  *
38  * This class is the access to openssl's ENGINE cryptographic module
39  * implementation.
40  *
41  * See also, https://www.openssl.org/docs/crypto/engine.html
42  */
44 /* Document-class: OpenSSL::Engine::EngineError
45  *
46  * This is the generic exception for OpenSSL::Engine related errors
47  */
49 
50 /*
51  * Private
52  */
53 #define OSSL_ENGINE_LOAD_IF_MATCH(x) \
54 do{\
55  if(!strcmp(#x, RSTRING_PTR(name))){\
56  ENGINE_load_##x();\
57  return Qtrue;\
58  }\
59 }while(0)
60 
61 static void
62 ossl_engine_free(void *engine)
63 {
64  ENGINE_free(engine);
65 }
66 
68  "OpenSSL/Engine",
69  {
71  },
73 };
74 
75 /* Document-method: OpenSSL::Engine.load
76  *
77  * call-seq:
78  * load(enginename = nil)
79  *
80  * This method loads engines. If +name+ is nil, then all builtin engines are
81  * loaded. Otherwise, the given +name+, as a string, is loaded if available to
82  * your runtime, and returns true. If +name+ is not found, then nil is
83  * returned.
84  *
85  */
86 static VALUE
88 {
89 #if !defined(HAVE_ENGINE_LOAD_BUILTIN_ENGINES)
90  return Qnil;
91 #else
92  VALUE name;
93 
94  rb_scan_args(argc, argv, "01", &name);
95  if(NIL_P(name)){
96  ENGINE_load_builtin_engines();
97  return Qtrue;
98  }
99  StringValueCStr(name);
100 #ifndef OPENSSL_NO_STATIC_ENGINE
101 #if HAVE_ENGINE_LOAD_DYNAMIC
102  OSSL_ENGINE_LOAD_IF_MATCH(dynamic);
103 #endif
104 #if HAVE_ENGINE_LOAD_4758CCA
105  OSSL_ENGINE_LOAD_IF_MATCH(4758cca);
106 #endif
107 #if HAVE_ENGINE_LOAD_AEP
109 #endif
110 #if HAVE_ENGINE_LOAD_ATALLA
112 #endif
113 #if HAVE_ENGINE_LOAD_CHIL
115 #endif
116 #if HAVE_ENGINE_LOAD_CSWIFT
118 #endif
119 #if HAVE_ENGINE_LOAD_NURON
121 #endif
122 #if HAVE_ENGINE_LOAD_SUREWARE
123  OSSL_ENGINE_LOAD_IF_MATCH(sureware);
124 #endif
125 #if HAVE_ENGINE_LOAD_UBSEC
127 #endif
128 #if HAVE_ENGINE_LOAD_PADLOCK
129  OSSL_ENGINE_LOAD_IF_MATCH(padlock);
130 #endif
131 #if HAVE_ENGINE_LOAD_CAPI
133 #endif
134 #if HAVE_ENGINE_LOAD_GMP
136 #endif
137 #if HAVE_ENGINE_LOAD_GOST
139 #endif
140 #if HAVE_ENGINE_LOAD_CRYPTODEV
141  OSSL_ENGINE_LOAD_IF_MATCH(cryptodev);
142 #endif
143 #if HAVE_ENGINE_LOAD_AESNI
145 #endif
146 #endif
147 #ifdef HAVE_ENGINE_LOAD_OPENBSD_DEV_CRYPTO
148  OSSL_ENGINE_LOAD_IF_MATCH(openbsd_dev_crypto);
149 #endif
150  OSSL_ENGINE_LOAD_IF_MATCH(openssl);
151  rb_warning("no such builtin loader for `%"PRIsVALUE"'", name);
152  return Qnil;
153 #endif /* HAVE_ENGINE_LOAD_BUILTIN_ENGINES */
154 }
155 
156 /* Document-method: OpenSSL::Engine.cleanup
157  * call-seq:
158  * OpenSSL::Engine.cleanup
159  *
160  * It is only necessary to run cleanup when engines are loaded via
161  * OpenSSL::Engine.load. However, running cleanup before exit is recommended.
162  *
163  * Note that this is needed and works only in OpenSSL < 1.1.0.
164  */
165 static VALUE
167 {
168  ENGINE_cleanup();
169  return Qnil;
170 }
171 
172 /* Document-method: OpenSSL::Engine.engines
173  *
174  * Returns an array of currently loaded engines.
175  */
176 static VALUE
178 {
179  ENGINE *e;
180  VALUE ary, obj;
181 
182  ary = rb_ary_new();
183  for(e = ENGINE_get_first(); e; e = ENGINE_get_next(e)){
184  obj = NewEngine(klass);
185  /* Need a ref count of two here because of ENGINE_free being
186  * called internally by OpenSSL when moving to the next ENGINE
187  * and by us when releasing the ENGINE reference */
188  ENGINE_up_ref(e);
189  SetEngine(obj, e);
190  rb_ary_push(ary, obj);
191  }
192 
193  return ary;
194 }
195 
196 /* Document-method: OpenSSL::Engine.by_id
197  *
198  * call-seq:
199  * by_id(name) -> engine
200  *
201  * Fetch the engine as specified by the +id+ String
202  *
203  * OpenSSL::Engine.by_id("openssl")
204  * => #<OpenSSL::Engine id="openssl" name="Software engine support">
205  *
206  * See OpenSSL::Engine.engines for the currently loaded engines
207  */
208 static VALUE
210 {
211  ENGINE *e;
212  VALUE obj;
213 
214  StringValueCStr(id);
215  ossl_engine_s_load(1, &id, klass);
216  obj = NewEngine(klass);
217  if(!(e = ENGINE_by_id(RSTRING_PTR(id))))
219  SetEngine(obj, e);
220  if(rb_block_given_p()) rb_yield(obj);
221  if(!ENGINE_init(e))
223  ENGINE_ctrl(e, ENGINE_CTRL_SET_PASSWORD_CALLBACK,
224  0, NULL, (void(*)(void))ossl_pem_passwd_cb);
226 
227  return obj;
228 }
229 
230 /* Document-method: OpenSSL::Engine#id
231  *
232  * Get the id for this engine
233  *
234  * OpenSSL::Engine.load
235  * OpenSSL::Engine.engines #=> [#<OpenSSL::Engine#>, ...]
236  * OpenSSL::Engine.engines.first.id
237  * #=> "rsax"
238  */
239 static VALUE
241 {
242  ENGINE *e;
243  GetEngine(self, e);
244  return rb_str_new2(ENGINE_get_id(e));
245 }
246 
247 /* Document-method: OpenSSL::Engine#name
248  *
249  * Get the descriptive name for this engine
250  *
251  * OpenSSL::Engine.load
252  * OpenSSL::Engine.engines #=> [#<OpenSSL::Engine#>, ...]
253  * OpenSSL::Engine.engines.first.name
254  * #=> "RSAX engine support"
255  *
256  */
257 static VALUE
259 {
260  ENGINE *e;
261  GetEngine(self, e);
262  return rb_str_new2(ENGINE_get_name(e));
263 }
264 
265 /* Document-method: OpenSSL::Engine#finish
266  *
267  * Releases all internal structural references for this engine.
268  *
269  * May raise an EngineError if the engine is unavailable
270  */
271 static VALUE
273 {
274  ENGINE *e;
275 
276  GetEngine(self, e);
277  if(!ENGINE_finish(e)) ossl_raise(eEngineError, NULL);
278 
279  return Qnil;
280 }
281 
282 /* Document-method: OpenSSL::Engine#cipher
283  *
284  * call-seq:
285  * engine.cipher(name) -> OpenSSL::Cipher
286  *
287  * This returns an OpenSSL::Cipher by +name+, if it is available in this
288  * engine.
289  *
290  * An EngineError will be raised if the cipher is unavailable.
291  *
292  * e = OpenSSL::Engine.by_id("openssl")
293  * => #<OpenSSL::Engine id="openssl" name="Software engine support">
294  * e.cipher("RC4")
295  * => #<OpenSSL::Cipher:0x007fc5cacc3048>
296  *
297  */
298 static VALUE
300 {
301  ENGINE *e;
302  const EVP_CIPHER *ciph, *tmp;
303  int nid;
304 
305  tmp = EVP_get_cipherbyname(StringValueCStr(name));
306  if(!tmp) ossl_raise(eEngineError, "no such cipher `%"PRIsVALUE"'", name);
307  nid = EVP_CIPHER_nid(tmp);
308  GetEngine(self, e);
309  ciph = ENGINE_get_cipher(e, nid);
310  if(!ciph) ossl_raise(eEngineError, NULL);
311 
312  return ossl_cipher_new(ciph);
313 }
314 
315 /* Document-method: OpenSSL::Engine#digest
316  *
317  * call-seq:
318  * engine.digest(name) -> OpenSSL::Digest
319  *
320  * This returns an OpenSSL::Digest by +name+.
321  *
322  * Will raise an EngineError if the digest is unavailable.
323  *
324  * e = OpenSSL::Engine.by_id("openssl")
325  * #=> #<OpenSSL::Engine id="openssl" name="Software engine support">
326  * e.digest("SHA1")
327  * #=> #<OpenSSL::Digest: da39a3ee5e6b4b0d3255bfef95601890afd80709>
328  * e.digest("zomg")
329  * #=> OpenSSL::Engine::EngineError: no such digest `zomg'
330  */
331 static VALUE
333 {
334  ENGINE *e;
335  const EVP_MD *md, *tmp;
336  int nid;
337 
338  tmp = EVP_get_digestbyname(StringValueCStr(name));
339  if(!tmp) ossl_raise(eEngineError, "no such digest `%"PRIsVALUE"'", name);
340  nid = EVP_MD_nid(tmp);
341  GetEngine(self, e);
342  md = ENGINE_get_digest(e, nid);
343  if(!md) ossl_raise(eEngineError, NULL);
344 
345  return ossl_digest_new(md);
346 }
347 
348 /* Document-method: OpenSSL::Engine#load_private_key
349  *
350  * call-seq:
351  * engine.load_private_key(id = nil, data = nil) -> OpenSSL::PKey
352  *
353  * Loads the given private key by +id+ and +data+.
354  *
355  * An EngineError is raised of the OpenSSL::PKey is unavailable.
356  *
357  */
358 static VALUE
360 {
361  ENGINE *e;
362  EVP_PKEY *pkey;
363  VALUE id, data, obj;
364  char *sid, *sdata;
365 
366  rb_scan_args(argc, argv, "02", &id, &data);
367  sid = NIL_P(id) ? NULL : StringValueCStr(id);
368  sdata = NIL_P(data) ? NULL : StringValueCStr(data);
369  GetEngine(self, e);
370  pkey = ENGINE_load_private_key(e, sid, NULL, sdata);
371  if (!pkey) ossl_raise(eEngineError, NULL);
372  obj = ossl_pkey_new(pkey);
374 
375  return obj;
376 }
377 
378 /* Document-method: OpenSSL::Engine#load_public_key
379  *
380  * call-seq:
381  * engine.load_public_key(id = nil, data = nil) -> OpenSSL::PKey
382  *
383  * Loads the given private key by +id+ and +data+.
384  *
385  * An EngineError is raised of the OpenSSL::PKey is unavailable.
386  *
387  */
388 static VALUE
390 {
391  ENGINE *e;
392  EVP_PKEY *pkey;
393  VALUE id, data;
394  char *sid, *sdata;
395 
396  rb_scan_args(argc, argv, "02", &id, &data);
397  sid = NIL_P(id) ? NULL : StringValueCStr(id);
398  sdata = NIL_P(data) ? NULL : StringValueCStr(data);
399  GetEngine(self, e);
400  pkey = ENGINE_load_public_key(e, sid, NULL, sdata);
401  if (!pkey) ossl_raise(eEngineError, NULL);
402 
403  return ossl_pkey_new(pkey);
404 }
405 
406 /* Document-method: OpenSSL::Engine#set_default
407  *
408  * call-seq:
409  * engine.set_default(flag)
410  *
411  * Set the defaults for this engine with the given +flag+.
412  *
413  * These flags are used to control combinations of algorithm methods.
414  *
415  * +flag+ can be one of the following, other flags are available depending on
416  * your OS.
417  *
418  * [All flags] 0xFFFF
419  * [No flags] 0x0000
420  *
421  * See also <openssl/engine.h>
422  */
423 static VALUE
425 {
426  ENGINE *e;
427  int f = NUM2INT(flag);
428 
429  GetEngine(self, e);
430  ENGINE_set_default(e, f);
431 
432  return Qtrue;
433 }
434 
435 /* Document-method: OpenSSL::Engine#ctrl_cmd
436  *
437  * call-seq:
438  * engine.ctrl_cmd(command, value = nil) -> engine
439  *
440  * Send the given +command+ to this engine.
441  *
442  * Raises an EngineError if the +command+ fails.
443  */
444 static VALUE
446 {
447  ENGINE *e;
448  VALUE cmd, val;
449  int ret;
450 
451  GetEngine(self, e);
452  rb_scan_args(argc, argv, "11", &cmd, &val);
453  ret = ENGINE_ctrl_cmd_string(e, StringValueCStr(cmd),
454  NIL_P(val) ? NULL : StringValueCStr(val), 0);
455  if (!ret) ossl_raise(eEngineError, NULL);
456 
457  return self;
458 }
459 
460 static VALUE
462 {
463  switch(flag){
464  case ENGINE_CMD_FLAG_NUMERIC: return rb_str_new2("NUMERIC");
465  case ENGINE_CMD_FLAG_STRING: return rb_str_new2("STRING");
466  case ENGINE_CMD_FLAG_NO_INPUT: return rb_str_new2("NO_INPUT");
467  case ENGINE_CMD_FLAG_INTERNAL: return rb_str_new2("INTERNAL");
468  default: return rb_str_new2("UNKNOWN");
469  }
470 }
471 
472 /* Document-method: OpenSSL::Engine#cmds
473  *
474  * Returns an array of command definitions for the current engine
475  */
476 static VALUE
478 {
479  ENGINE *e;
480  const ENGINE_CMD_DEFN *defn, *p;
481  VALUE ary, tmp;
482 
483  GetEngine(self, e);
484  ary = rb_ary_new();
485  if ((defn = ENGINE_get_cmd_defns(e)) != NULL){
486  for (p = defn; p->cmd_num > 0; p++){
487  tmp = rb_ary_new();
488  rb_ary_push(tmp, rb_str_new2(p->cmd_name));
489  rb_ary_push(tmp, rb_str_new2(p->cmd_desc));
490  rb_ary_push(tmp, ossl_engine_cmd_flag_to_name(p->cmd_flags));
491  rb_ary_push(ary, tmp);
492  }
493  }
494 
495  return ary;
496 }
497 
498 /* Document-method: OpenSSL::Engine#inspect
499  *
500  * Pretty print this engine
501  */
502 static VALUE
504 {
505  ENGINE *e;
506 
507  GetEngine(self, e);
508  return rb_sprintf("#<%"PRIsVALUE" id=\"%s\" name=\"%s\">",
509  rb_obj_class(self), ENGINE_get_id(e), ENGINE_get_name(e));
510 }
511 
512 #define DefEngineConst(x) rb_define_const(cEngine, #x, INT2NUM(ENGINE_##x))
513 
514 void
516 {
517 #if 0
518  mOSSL = rb_define_module("OpenSSL");
520 #endif
521 
524 
530 
536  rb_define_method(cEngine, "load_private_key", ossl_engine_load_privkey, -1);
537  rb_define_method(cEngine, "load_public_key", ossl_engine_load_pubkey, -1);
542 
543  DefEngineConst(METHOD_RSA);
544  DefEngineConst(METHOD_DSA);
545  DefEngineConst(METHOD_DH);
546  DefEngineConst(METHOD_RAND);
547 #ifdef ENGINE_METHOD_BN_MOD_EXP
548  DefEngineConst(METHOD_BN_MOD_EXP);
549 #endif
550 #ifdef ENGINE_METHOD_BN_MOD_EXP_CRT
551  DefEngineConst(METHOD_BN_MOD_EXP_CRT);
552 #endif
553  DefEngineConst(METHOD_CIPHERS);
554  DefEngineConst(METHOD_DIGESTS);
555  DefEngineConst(METHOD_ALL);
556  DefEngineConst(METHOD_NONE);
557 }
558 #else
559 void
560 Init_ossl_engine(void)
561 {
562 }
563 #endif
static VALUE ossl_engine_get_digest(VALUE self, VALUE name)
Definition: ossl_engine.c:332
#define SetEngine(obj, engine)
Definition: ossl_engine.c:16
VALUE rb_eStandardError
Definition: error.c:760
static VALUE ossl_engine_get_id(VALUE self)
Definition: ossl_engine.c:240
VALUE mOSSL
Definition: ossl.c:213
static VALUE ossl_engine_s_cleanup(VALUE self)
Definition: ossl_engine.c:166
#define RUBY_TYPED_FREE_IMMEDIATELY
Definition: ruby.h:1145
#define GetEngine(obj, engine)
Definition: ossl_engine.c:22
#define NUM2INT(x)
Definition: ruby.h:684
void rb_undef_alloc_func(VALUE)
Definition: vm_method.c:681
void rb_define_singleton_method(VALUE obj, const char *name, VALUE(*func)(ANYARGS), int argc)
Defines a singleton method for obj.
Definition: class.c:1716
static VALUE ossl_engine_cmd_flag_to_name(int flag)
Definition: ossl_engine.c:461
#define Qtrue
Definition: ruby.h:437
void Init_ossl_engine(void)
Definition: ossl_engine.c:515
const int id
Definition: nkf.c:209
VALUE cEngine
Definition: ossl_engine.c:43
VALUE rb_ary_push(VALUE ary, VALUE item)
Definition: array.c:905
static VALUE ossl_engine_load_privkey(int argc, VALUE *argv, VALUE self)
Definition: ossl_engine.c:359
VALUE rb_define_class_under(VALUE outer, const char *name, VALUE super)
Defines a class under the namespace of outer.
Definition: class.c:693
VALUE ossl_pkey_new(EVP_PKEY *pkey)
Definition: ossl_pkey.c:107
static VALUE ossl_engine_finish(VALUE self)
Definition: ossl_engine.c:272
#define DefEngineConst(x)
Definition: ossl_engine.c:512
VALUE ossl_cipher_new(const EVP_CIPHER *cipher)
Definition: ossl_cipher.c:79
#define OSSL_PKEY_SET_PRIVATE(obj)
Definition: ossl_pkey.h:18
void ossl_clear_error(void)
Definition: ossl.c:289
int rb_block_given_p(void)
Definition: eval.c:797
static VALUE ossl_engine_get_cmds(VALUE self)
Definition: ossl_engine.c:477
#define val
RUBY_EXTERN VALUE rb_cObject
Definition: ruby.h:1872
#define NewEngine(klass)
Definition: ossl_engine.c:14
VALUE rb_ary_new(void)
Definition: array.c:493
VALUE ossl_digest_new(const EVP_MD *md)
Definition: ossl_digest.c:77
#define NIL_P(v)
Definition: ruby.h:451
VALUE eOSSLError
Definition: ossl.c:218
int argc
Definition: ruby.c:183
static VALUE ossl_engine_s_engines(VALUE klass)
Definition: ossl_engine.c:177
static VALUE ossl_engine_s_load(int argc, VALUE *argv, VALUE klass)
Definition: ossl_engine.c:87
#define OSSL_ENGINE_LOAD_IF_MATCH(x)
Definition: ossl_engine.c:53
static const rb_data_type_t ossl_engine_type
Definition: ossl_engine.c:67
#define rb_str_new2
Definition: intern.h:857
int ossl_pem_passwd_cb(char *buf, int max_len, int flag, void *pwd_)
Definition: ossl.c:159
VALUE rb_yield(VALUE)
Definition: vm_eval.c:1020
VALUE rb_sprintf(const char *format,...)
Definition: sprintf.c:1440
static VALUE ossl_engine_inspect(VALUE self)
Definition: ossl_engine.c:503
int rb_scan_args(int argc, const VALUE *argv, const char *fmt,...)
Definition: class.c:1919
static VALUE ossl_engine_ctrl_cmd(int argc, VALUE *argv, VALUE self)
Definition: ossl_engine.c:445
#define PRIsVALUE
Definition: ruby.h:135
static VALUE ossl_engine_get_name(VALUE self)
Definition: ossl_engine.c:258
#define Qnil
Definition: ruby.h:438
unsigned long VALUE
Definition: ruby.h:85
#define StringValueCStr(v)
Definition: ruby.h:571
#define RSTRING_PTR(str)
Definition: ruby.h:982
#define f
static VALUE ossl_engine_get_cipher(VALUE self, VALUE name)
Definition: ossl_engine.c:299
static VALUE ossl_engine_load_pubkey(int argc, VALUE *argv, VALUE self)
Definition: ossl_engine.c:389
void ossl_raise(VALUE exc, const char *fmt,...)
Definition: ossl.c:278
const char * name
Definition: nkf.c:208
VALUE eEngineError
Definition: ossl_engine.c:48
int nid
void rb_warning(const char *fmt,...)
Definition: error.c:250
VALUE rb_define_module(const char *name)
Definition: class.c:768
static VALUE ossl_engine_set_default(VALUE self, VALUE flag)
Definition: ossl_engine.c:424
#define NULL
Definition: _sdbm.c:102
static VALUE ossl_engine_s_by_id(VALUE klass, VALUE id)
Definition: ossl_engine.c:209
void rb_define_method(VALUE klass, const char *name, VALUE(*func)(ANYARGS), int argc)
Definition: class.c:1515
static void ossl_engine_free(void *engine)
Definition: ossl_engine.c:62
char ** argv
Definition: ruby.c:184
VALUE rb_obj_class(VALUE)
Definition: object.c:229