openssl-custom 2.2.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (75) hide show
  1. checksums.yaml +7 -0
  2. data/BSDL +22 -0
  3. data/CONTRIBUTING.md +132 -0
  4. data/History.md +485 -0
  5. data/LICENSE.txt +56 -0
  6. data/README.md +66 -0
  7. data/ext/openssl/extconf.rb +190 -0
  8. data/ext/openssl/openssl_missing.c +106 -0
  9. data/ext/openssl/openssl_missing.h +257 -0
  10. data/ext/openssl/ossl.c +1282 -0
  11. data/ext/openssl/ossl.h +181 -0
  12. data/ext/openssl/ossl_asn1.c +1878 -0
  13. data/ext/openssl/ossl_asn1.h +62 -0
  14. data/ext/openssl/ossl_bio.c +42 -0
  15. data/ext/openssl/ossl_bio.h +16 -0
  16. data/ext/openssl/ossl_bn.c +1270 -0
  17. data/ext/openssl/ossl_bn.h +26 -0
  18. data/ext/openssl/ossl_cipher.c +1075 -0
  19. data/ext/openssl/ossl_cipher.h +20 -0
  20. data/ext/openssl/ossl_config.c +89 -0
  21. data/ext/openssl/ossl_config.h +19 -0
  22. data/ext/openssl/ossl_digest.c +425 -0
  23. data/ext/openssl/ossl_digest.h +20 -0
  24. data/ext/openssl/ossl_engine.c +567 -0
  25. data/ext/openssl/ossl_engine.h +19 -0
  26. data/ext/openssl/ossl_hmac.c +389 -0
  27. data/ext/openssl/ossl_hmac.h +18 -0
  28. data/ext/openssl/ossl_kdf.c +303 -0
  29. data/ext/openssl/ossl_kdf.h +6 -0
  30. data/ext/openssl/ossl_ns_spki.c +405 -0
  31. data/ext/openssl/ossl_ns_spki.h +19 -0
  32. data/ext/openssl/ossl_ocsp.c +2013 -0
  33. data/ext/openssl/ossl_ocsp.h +23 -0
  34. data/ext/openssl/ossl_pkcs12.c +257 -0
  35. data/ext/openssl/ossl_pkcs12.h +13 -0
  36. data/ext/openssl/ossl_pkcs7.c +1098 -0
  37. data/ext/openssl/ossl_pkcs7.h +36 -0
  38. data/ext/openssl/ossl_pkey.c +673 -0
  39. data/ext/openssl/ossl_pkey.h +241 -0
  40. data/ext/openssl/ossl_pkey_dh.c +650 -0
  41. data/ext/openssl/ossl_pkey_dsa.c +664 -0
  42. data/ext/openssl/ossl_pkey_ec.c +1827 -0
  43. data/ext/openssl/ossl_pkey_rsa.c +966 -0
  44. data/ext/openssl/ossl_rand.c +200 -0
  45. data/ext/openssl/ossl_rand.h +18 -0
  46. data/ext/openssl/ossl_ssl.c +3080 -0
  47. data/ext/openssl/ossl_ssl.h +36 -0
  48. data/ext/openssl/ossl_ssl_session.c +332 -0
  49. data/ext/openssl/ossl_ts.c +1524 -0
  50. data/ext/openssl/ossl_ts.h +16 -0
  51. data/ext/openssl/ossl_x509.c +262 -0
  52. data/ext/openssl/ossl_x509.h +115 -0
  53. data/ext/openssl/ossl_x509attr.c +324 -0
  54. data/ext/openssl/ossl_x509cert.c +846 -0
  55. data/ext/openssl/ossl_x509crl.c +542 -0
  56. data/ext/openssl/ossl_x509ext.c +491 -0
  57. data/ext/openssl/ossl_x509name.c +590 -0
  58. data/ext/openssl/ossl_x509req.c +441 -0
  59. data/ext/openssl/ossl_x509revoked.c +300 -0
  60. data/ext/openssl/ossl_x509store.c +902 -0
  61. data/ext/openssl/ruby_missing.h +24 -0
  62. data/lib/openssl/bn.rb +40 -0
  63. data/lib/openssl/buffering.rb +478 -0
  64. data/lib/openssl/cipher.rb +67 -0
  65. data/lib/openssl/config.rb +501 -0
  66. data/lib/openssl/digest.rb +73 -0
  67. data/lib/openssl/hmac.rb +13 -0
  68. data/lib/openssl/marshal.rb +30 -0
  69. data/lib/openssl/pkcs5.rb +22 -0
  70. data/lib/openssl/pkey.rb +42 -0
  71. data/lib/openssl/ssl.rb +542 -0
  72. data/lib/openssl/version.rb +5 -0
  73. data/lib/openssl/x509.rb +369 -0
  74. data/lib/openssl.rb +38 -0
  75. metadata +196 -0
@@ -0,0 +1,1282 @@
1
+ /*
2
+ * 'OpenSSL for Ruby' project
3
+ * Copyright (C) 2001-2002 Michal Rokos <m.rokos@sh.cvut.cz>
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
+ #include <stdarg.h> /* for ossl_raise */
12
+ #include <ruby/thread_native.h> /* for OpenSSL < 1.1.0 locks */
13
+
14
+ /*
15
+ * Data Conversion
16
+ */
17
+ #define OSSL_IMPL_ARY2SK(name, type, expected_class, dup) \
18
+ STACK_OF(type) * \
19
+ ossl_##name##_ary2sk0(VALUE ary) \
20
+ { \
21
+ STACK_OF(type) *sk; \
22
+ VALUE val; \
23
+ type *x; \
24
+ int i; \
25
+ \
26
+ Check_Type(ary, T_ARRAY); \
27
+ sk = sk_##type##_new_null(); \
28
+ if (!sk) ossl_raise(eOSSLError, NULL); \
29
+ \
30
+ for (i = 0; i < RARRAY_LEN(ary); i++) { \
31
+ val = rb_ary_entry(ary, i); \
32
+ if (!rb_obj_is_kind_of(val, expected_class)) { \
33
+ sk_##type##_pop_free(sk, type##_free); \
34
+ ossl_raise(eOSSLError, "object in array not" \
35
+ " of class ##type##"); \
36
+ } \
37
+ x = dup(val); /* NEED TO DUP */ \
38
+ sk_##type##_push(sk, x); \
39
+ } \
40
+ return sk; \
41
+ } \
42
+ \
43
+ STACK_OF(type) * \
44
+ ossl_protect_##name##_ary2sk(VALUE ary, int *status) \
45
+ { \
46
+ return (STACK_OF(type)*)rb_protect( \
47
+ (VALUE (*)(VALUE))ossl_##name##_ary2sk0, \
48
+ ary, \
49
+ status); \
50
+ } \
51
+ \
52
+ STACK_OF(type) * \
53
+ ossl_##name##_ary2sk(VALUE ary) \
54
+ { \
55
+ STACK_OF(type) *sk; \
56
+ int status = 0; \
57
+ \
58
+ sk = ossl_protect_##name##_ary2sk(ary, &status); \
59
+ if (status) rb_jump_tag(status); \
60
+ \
61
+ return sk; \
62
+ }
63
+ OSSL_IMPL_ARY2SK(x509, X509, cX509Cert, DupX509CertPtr)
64
+
65
+ #define OSSL_IMPL_SK2ARY(name, type) \
66
+ VALUE \
67
+ ossl_##name##_sk2ary(const STACK_OF(type) *sk) \
68
+ { \
69
+ type *t; \
70
+ int i, num; \
71
+ VALUE ary; \
72
+ \
73
+ if (!sk) { \
74
+ OSSL_Debug("empty sk!"); \
75
+ return Qnil; \
76
+ } \
77
+ num = sk_##type##_num(sk); \
78
+ if (num < 0) { \
79
+ OSSL_Debug("items in sk < -1???"); \
80
+ return rb_ary_new(); \
81
+ } \
82
+ ary = rb_ary_new2(num); \
83
+ \
84
+ for (i=0; i<num; i++) { \
85
+ t = sk_##type##_value(sk, i); \
86
+ rb_ary_push(ary, ossl_##name##_new(t)); \
87
+ } \
88
+ return ary; \
89
+ }
90
+ OSSL_IMPL_SK2ARY(x509, X509)
91
+ OSSL_IMPL_SK2ARY(x509crl, X509_CRL)
92
+ OSSL_IMPL_SK2ARY(x509name, X509_NAME)
93
+
94
+ static VALUE
95
+ ossl_str_new_i(VALUE size)
96
+ {
97
+ return rb_str_new(NULL, (long)size);
98
+ }
99
+
100
+ VALUE
101
+ ossl_str_new(const char *ptr, long len, int *pstate)
102
+ {
103
+ VALUE str;
104
+ int state;
105
+
106
+ str = rb_protect(ossl_str_new_i, len, &state);
107
+ if (pstate)
108
+ *pstate = state;
109
+ if (state) {
110
+ if (!pstate)
111
+ rb_set_errinfo(Qnil);
112
+ return Qnil;
113
+ }
114
+ if (ptr)
115
+ memcpy(RSTRING_PTR(str), ptr, len);
116
+ return str;
117
+ }
118
+
119
+ VALUE
120
+ ossl_buf2str(char *buf, int len)
121
+ {
122
+ VALUE str;
123
+ int state;
124
+
125
+ str = ossl_str_new(buf, len, &state);
126
+ OPENSSL_free(buf);
127
+ if (state)
128
+ rb_jump_tag(state);
129
+ return str;
130
+ }
131
+
132
+ void
133
+ ossl_bin2hex(unsigned char *in, char *out, size_t inlen)
134
+ {
135
+ const char *hex = "0123456789abcdef";
136
+ size_t i;
137
+
138
+ assert(inlen <= LONG_MAX / 2);
139
+ for (i = 0; i < inlen; i++) {
140
+ unsigned char p = in[i];
141
+
142
+ out[i * 2 + 0] = hex[p >> 4];
143
+ out[i * 2 + 1] = hex[p & 0x0f];
144
+ }
145
+ }
146
+
147
+ /*
148
+ * our default PEM callback
149
+ */
150
+ VALUE
151
+ ossl_pem_passwd_value(VALUE pass)
152
+ {
153
+ if (NIL_P(pass))
154
+ return Qnil;
155
+
156
+ StringValue(pass);
157
+
158
+ /* PEM_BUFSIZE is currently used as the second argument of pem_password_cb,
159
+ * that is +max_len+ of ossl_pem_passwd_cb() */
160
+ if (RSTRING_LEN(pass) > PEM_BUFSIZE)
161
+ ossl_raise(eOSSLError, "password must not be longer than %d bytes", PEM_BUFSIZE);
162
+
163
+ return pass;
164
+ }
165
+
166
+ static VALUE
167
+ ossl_pem_passwd_cb0(VALUE flag)
168
+ {
169
+ VALUE pass = rb_yield(flag);
170
+ if (NIL_P(pass))
171
+ return Qnil;
172
+ StringValue(pass);
173
+ return pass;
174
+ }
175
+
176
+ int
177
+ ossl_pem_passwd_cb(char *buf, int max_len, int flag, void *pwd_)
178
+ {
179
+ long len;
180
+ int status;
181
+ VALUE rflag, pass = (VALUE)pwd_;
182
+
183
+ if (RTEST(pass)) {
184
+ /* PEM_def_callback(buf, max_len, flag, StringValueCStr(pass)) does not
185
+ * work because it does not allow NUL characters and truncates to 1024
186
+ * bytes silently if the input is over 1024 bytes */
187
+ if (RB_TYPE_P(pass, T_STRING)) {
188
+ len = RSTRING_LEN(pass);
189
+ if (len <= max_len) {
190
+ memcpy(buf, RSTRING_PTR(pass), len);
191
+ return (int)len;
192
+ }
193
+ }
194
+ OSSL_Debug("passed data is not valid String???");
195
+ return -1;
196
+ }
197
+
198
+ if (!rb_block_given_p()) {
199
+ return PEM_def_callback(buf, max_len, flag, NULL);
200
+ }
201
+
202
+ while (1) {
203
+ /*
204
+ * when the flag is nonzero, this passphrase
205
+ * will be used to perform encryption; otherwise it will
206
+ * be used to perform decryption.
207
+ */
208
+ rflag = flag ? Qtrue : Qfalse;
209
+ pass = rb_protect(ossl_pem_passwd_cb0, rflag, &status);
210
+ if (status) {
211
+ /* ignore an exception raised. */
212
+ rb_set_errinfo(Qnil);
213
+ return -1;
214
+ }
215
+ if (NIL_P(pass))
216
+ return -1;
217
+ len = RSTRING_LEN(pass);
218
+ if (len > max_len) {
219
+ rb_warning("password must not be longer than %d bytes", max_len);
220
+ continue;
221
+ }
222
+ memcpy(buf, RSTRING_PTR(pass), len);
223
+ break;
224
+ }
225
+ return (int)len;
226
+ }
227
+
228
+ /*
229
+ * main module
230
+ */
231
+ VALUE mOSSL;
232
+
233
+ /*
234
+ * OpenSSLError < StandardError
235
+ */
236
+ VALUE eOSSLError;
237
+
238
+ /*
239
+ * Convert to DER string
240
+ */
241
+ static ID ossl_s_to_der;
242
+
243
+ VALUE
244
+ ossl_to_der(VALUE obj)
245
+ {
246
+ VALUE tmp;
247
+
248
+ tmp = rb_funcall(obj, ossl_s_to_der, 0);
249
+ StringValue(tmp);
250
+
251
+ return tmp;
252
+ }
253
+
254
+ VALUE
255
+ ossl_to_der_if_possible(VALUE obj)
256
+ {
257
+ if(rb_respond_to(obj, ossl_s_to_der))
258
+ return ossl_to_der(obj);
259
+ return obj;
260
+ }
261
+
262
+ /*
263
+ * Errors
264
+ */
265
+ static VALUE
266
+ ossl_make_error(VALUE exc, const char *fmt, va_list args)
267
+ {
268
+ VALUE str = Qnil;
269
+ unsigned long e;
270
+
271
+ if (fmt) {
272
+ str = rb_vsprintf(fmt, args);
273
+ }
274
+ e = ERR_peek_last_error();
275
+ if (e) {
276
+ const char *msg = ERR_reason_error_string(e);
277
+
278
+ if (NIL_P(str)) {
279
+ if (msg) str = rb_str_new_cstr(msg);
280
+ }
281
+ else {
282
+ if (RSTRING_LEN(str)) rb_str_cat2(str, ": ");
283
+ rb_str_cat2(str, msg ? msg : "(null)");
284
+ }
285
+ ossl_clear_error();
286
+ }
287
+
288
+ if (NIL_P(str)) str = rb_str_new(0, 0);
289
+ return rb_exc_new3(exc, str);
290
+ }
291
+
292
+ void
293
+ ossl_raise(VALUE exc, const char *fmt, ...)
294
+ {
295
+ va_list args;
296
+ VALUE err;
297
+ va_start(args, fmt);
298
+ err = ossl_make_error(exc, fmt, args);
299
+ va_end(args);
300
+ rb_exc_raise(err);
301
+ }
302
+
303
+ void
304
+ ossl_clear_error(void)
305
+ {
306
+ if (dOSSL == Qtrue) {
307
+ unsigned long e;
308
+ const char *file, *data, *errstr;
309
+ int line, flags;
310
+
311
+ while ((e = ERR_get_error_line_data(&file, &line, &data, &flags))) {
312
+ errstr = ERR_error_string(e, NULL);
313
+ if (!errstr)
314
+ errstr = "(null)";
315
+
316
+ if (flags & ERR_TXT_STRING) {
317
+ if (!data)
318
+ data = "(null)";
319
+ rb_warn("error on stack: %s (%s)", errstr, data);
320
+ }
321
+ else {
322
+ rb_warn("error on stack: %s", errstr);
323
+ }
324
+ }
325
+ }
326
+ else {
327
+ ERR_clear_error();
328
+ }
329
+ }
330
+
331
+ /*
332
+ * call-seq:
333
+ * OpenSSL.errors -> [String...]
334
+ *
335
+ * See any remaining errors held in queue.
336
+ *
337
+ * Any errors you see here are probably due to a bug in Ruby's OpenSSL
338
+ * implementation.
339
+ */
340
+ VALUE
341
+ ossl_get_errors(VALUE _)
342
+ {
343
+ VALUE ary;
344
+ long e;
345
+
346
+ ary = rb_ary_new();
347
+ while ((e = ERR_get_error()) != 0){
348
+ rb_ary_push(ary, rb_str_new2(ERR_error_string(e, NULL)));
349
+ }
350
+
351
+ return ary;
352
+ }
353
+
354
+ /*
355
+ * Debug
356
+ */
357
+ VALUE dOSSL;
358
+
359
+ #if !defined(HAVE_VA_ARGS_MACRO)
360
+ void
361
+ ossl_debug(const char *fmt, ...)
362
+ {
363
+ va_list args;
364
+
365
+ if (dOSSL == Qtrue) {
366
+ fprintf(stderr, "OSSL_DEBUG: ");
367
+ va_start(args, fmt);
368
+ vfprintf(stderr, fmt, args);
369
+ va_end(args);
370
+ fprintf(stderr, " [CONTEXT N/A]\n");
371
+ }
372
+ }
373
+ #endif
374
+
375
+ /*
376
+ * call-seq:
377
+ * OpenSSL.debug -> true | false
378
+ */
379
+ static VALUE
380
+ ossl_debug_get(VALUE self)
381
+ {
382
+ return dOSSL;
383
+ }
384
+
385
+ /*
386
+ * call-seq:
387
+ * OpenSSL.debug = boolean -> boolean
388
+ *
389
+ * Turns on or off debug mode. With debug mode, all erros added to the OpenSSL
390
+ * error queue will be printed to stderr.
391
+ */
392
+ static VALUE
393
+ ossl_debug_set(VALUE self, VALUE val)
394
+ {
395
+ dOSSL = RTEST(val) ? Qtrue : Qfalse;
396
+
397
+ return val;
398
+ }
399
+
400
+ /*
401
+ * call-seq:
402
+ * OpenSSL.fips_mode -> true | false
403
+ */
404
+ static VALUE
405
+ ossl_fips_mode_get(VALUE self)
406
+ {
407
+
408
+ #ifdef OPENSSL_FIPS
409
+ VALUE enabled;
410
+ enabled = FIPS_mode() ? Qtrue : Qfalse;
411
+ return enabled;
412
+ #else
413
+ return Qfalse;
414
+ #endif
415
+ }
416
+
417
+ /*
418
+ * call-seq:
419
+ * OpenSSL.fips_mode = boolean -> boolean
420
+ *
421
+ * Turns FIPS mode on or off. Turning on FIPS mode will obviously only have an
422
+ * effect for FIPS-capable installations of the OpenSSL library. Trying to do
423
+ * so otherwise will result in an error.
424
+ *
425
+ * === Examples
426
+ * OpenSSL.fips_mode = true # turn FIPS mode on
427
+ * OpenSSL.fips_mode = false # and off again
428
+ */
429
+ static VALUE
430
+ ossl_fips_mode_set(VALUE self, VALUE enabled)
431
+ {
432
+
433
+ #ifdef OPENSSL_FIPS
434
+ if (RTEST(enabled)) {
435
+ int mode = FIPS_mode();
436
+ if(!mode && !FIPS_mode_set(1)) /* turning on twice leads to an error */
437
+ ossl_raise(eOSSLError, "Turning on FIPS mode failed");
438
+ } else {
439
+ if(!FIPS_mode_set(0)) /* turning off twice is OK */
440
+ ossl_raise(eOSSLError, "Turning off FIPS mode failed");
441
+ }
442
+ return enabled;
443
+ #else
444
+ if (RTEST(enabled))
445
+ ossl_raise(eOSSLError, "This version of OpenSSL does not support FIPS mode");
446
+ return enabled;
447
+ #endif
448
+ }
449
+
450
+ #if defined(OSSL_DEBUG)
451
+ #if !defined(LIBRESSL_VERSION_NUMBER) && \
452
+ (OPENSSL_VERSION_NUMBER >= 0x10100000 && !defined(OPENSSL_NO_CRYPTO_MDEBUG) || \
453
+ defined(CRYPTO_malloc_debug_init))
454
+ /*
455
+ * call-seq:
456
+ * OpenSSL.mem_check_start -> nil
457
+ *
458
+ * Calls CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ON). Starts tracking memory
459
+ * allocations. See also OpenSSL.print_mem_leaks.
460
+ *
461
+ * This is available only when built with a capable OpenSSL and --enable-debug
462
+ * configure option.
463
+ */
464
+ static VALUE
465
+ mem_check_start(VALUE self)
466
+ {
467
+ CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ON);
468
+ return Qnil;
469
+ }
470
+
471
+ /*
472
+ * call-seq:
473
+ * OpenSSL.print_mem_leaks -> true | false
474
+ *
475
+ * For debugging the Ruby/OpenSSL library. Calls CRYPTO_mem_leaks_fp(stderr).
476
+ * Prints detected memory leaks to standard error. This cleans the global state
477
+ * up thus you cannot use any methods of the library after calling this.
478
+ *
479
+ * Returns +true+ if leaks detected, +false+ otherwise.
480
+ *
481
+ * This is available only when built with a capable OpenSSL and --enable-debug
482
+ * configure option.
483
+ *
484
+ * === Example
485
+ * OpenSSL.mem_check_start
486
+ * NOT_GCED = OpenSSL::PKey::RSA.new(256)
487
+ *
488
+ * END {
489
+ * GC.start
490
+ * OpenSSL.print_mem_leaks # will print the leakage
491
+ * }
492
+ */
493
+ static VALUE
494
+ print_mem_leaks(VALUE self)
495
+ {
496
+ #if OPENSSL_VERSION_NUMBER >= 0x10100000
497
+ int ret;
498
+ #endif
499
+
500
+ #ifndef HAVE_RB_EXT_RACTOR_SAFE
501
+ // for Ruby 2.x
502
+ void ossl_bn_ctx_free(void); // ossl_bn.c
503
+ ossl_bn_ctx_free();
504
+ #endif
505
+
506
+ #if OPENSSL_VERSION_NUMBER >= 0x10100000
507
+ ret = CRYPTO_mem_leaks_fp(stderr);
508
+ if (ret < 0)
509
+ ossl_raise(eOSSLError, "CRYPTO_mem_leaks_fp");
510
+ return ret ? Qfalse : Qtrue;
511
+ #else
512
+ CRYPTO_mem_leaks_fp(stderr);
513
+ return Qnil;
514
+ #endif
515
+ }
516
+ #endif
517
+ #endif
518
+
519
+ #if !defined(HAVE_OPENSSL_110_THREADING_API)
520
+ /**
521
+ * Stores locks needed for OpenSSL thread safety
522
+ */
523
+ struct CRYPTO_dynlock_value {
524
+ rb_nativethread_lock_t lock;
525
+ rb_nativethread_id_t owner;
526
+ size_t count;
527
+ };
528
+
529
+ static void
530
+ ossl_lock_init(struct CRYPTO_dynlock_value *l)
531
+ {
532
+ rb_nativethread_lock_initialize(&l->lock);
533
+ l->count = 0;
534
+ }
535
+
536
+ static void
537
+ ossl_lock_unlock(int mode, struct CRYPTO_dynlock_value *l)
538
+ {
539
+ if (mode & CRYPTO_LOCK) {
540
+ /* TODO: rb_nativethread_id_t is not necessarily compared with ==. */
541
+ rb_nativethread_id_t tid = rb_nativethread_self();
542
+ if (l->count && l->owner == tid) {
543
+ l->count++;
544
+ return;
545
+ }
546
+ rb_nativethread_lock_lock(&l->lock);
547
+ l->owner = tid;
548
+ l->count = 1;
549
+ } else {
550
+ if (!--l->count)
551
+ rb_nativethread_lock_unlock(&l->lock);
552
+ }
553
+ }
554
+
555
+ static struct CRYPTO_dynlock_value *
556
+ ossl_dyn_create_callback(const char *file, int line)
557
+ {
558
+ /* Do not use xmalloc() here, since it may raise NoMemoryError */
559
+ struct CRYPTO_dynlock_value *dynlock =
560
+ OPENSSL_malloc(sizeof(struct CRYPTO_dynlock_value));
561
+ if (dynlock)
562
+ ossl_lock_init(dynlock);
563
+ return dynlock;
564
+ }
565
+
566
+ static void
567
+ ossl_dyn_lock_callback(int mode, struct CRYPTO_dynlock_value *l, const char *file, int line)
568
+ {
569
+ ossl_lock_unlock(mode, l);
570
+ }
571
+
572
+ static void
573
+ ossl_dyn_destroy_callback(struct CRYPTO_dynlock_value *l, const char *file, int line)
574
+ {
575
+ rb_nativethread_lock_destroy(&l->lock);
576
+ OPENSSL_free(l);
577
+ }
578
+
579
+ static void ossl_threadid_func(CRYPTO_THREADID *id)
580
+ {
581
+ /* register native thread id */
582
+ CRYPTO_THREADID_set_pointer(id, (void *)rb_nativethread_self());
583
+ }
584
+
585
+ static struct CRYPTO_dynlock_value *ossl_locks;
586
+
587
+ static void
588
+ ossl_lock_callback(int mode, int type, const char *file, int line)
589
+ {
590
+ ossl_lock_unlock(mode, &ossl_locks[type]);
591
+ }
592
+
593
+ static void Init_ossl_locks(void)
594
+ {
595
+ int i;
596
+ int num_locks = CRYPTO_num_locks();
597
+
598
+ ossl_locks = ALLOC_N(struct CRYPTO_dynlock_value, num_locks);
599
+ for (i = 0; i < num_locks; i++)
600
+ ossl_lock_init(&ossl_locks[i]);
601
+
602
+ CRYPTO_THREADID_set_callback(ossl_threadid_func);
603
+ CRYPTO_set_locking_callback(ossl_lock_callback);
604
+ CRYPTO_set_dynlock_create_callback(ossl_dyn_create_callback);
605
+ CRYPTO_set_dynlock_lock_callback(ossl_dyn_lock_callback);
606
+ CRYPTO_set_dynlock_destroy_callback(ossl_dyn_destroy_callback);
607
+ }
608
+ #endif /* !HAVE_OPENSSL_110_THREADING_API */
609
+
610
+ /*
611
+ * call-seq:
612
+ * OpenSSL.fixed_length_secure_compare(string, string) -> boolean
613
+ *
614
+ * Constant time memory comparison for fixed length strings, such as results
615
+ * of HMAC calculations.
616
+ *
617
+ * Returns +true+ if the strings are identical, +false+ if they are of the same
618
+ * length but not identical. If the length is different, +ArgumentError+ is
619
+ * raised.
620
+ */
621
+ static VALUE
622
+ ossl_crypto_fixed_length_secure_compare(VALUE dummy, VALUE str1, VALUE str2)
623
+ {
624
+ const unsigned char *p1 = (const unsigned char *)StringValuePtr(str1);
625
+ const unsigned char *p2 = (const unsigned char *)StringValuePtr(str2);
626
+ long len1 = RSTRING_LEN(str1);
627
+ long len2 = RSTRING_LEN(str2);
628
+
629
+ if (len1 != len2) {
630
+ ossl_raise(rb_eArgError, "inputs must be of equal length");
631
+ }
632
+
633
+ switch (CRYPTO_memcmp(p1, p2, len1)) {
634
+ case 0: return Qtrue;
635
+ default: return Qfalse;
636
+ }
637
+ }
638
+
639
+ /*
640
+ * OpenSSL provides SSL, TLS and general purpose cryptography. It wraps the
641
+ * OpenSSL[https://www.openssl.org/] library.
642
+ *
643
+ * = Examples
644
+ *
645
+ * All examples assume you have loaded OpenSSL with:
646
+ *
647
+ * require 'openssl'
648
+ *
649
+ * These examples build atop each other. For example the key created in the
650
+ * next is used in throughout these examples.
651
+ *
652
+ * == Keys
653
+ *
654
+ * === Creating a Key
655
+ *
656
+ * This example creates a 2048 bit RSA keypair and writes it to the current
657
+ * directory.
658
+ *
659
+ * key = OpenSSL::PKey::RSA.new 2048
660
+ *
661
+ * open 'private_key.pem', 'w' do |io| io.write key.to_pem end
662
+ * open 'public_key.pem', 'w' do |io| io.write key.public_key.to_pem end
663
+ *
664
+ * === Exporting a Key
665
+ *
666
+ * Keys saved to disk without encryption are not secure as anyone who gets
667
+ * ahold of the key may use it unless it is encrypted. In order to securely
668
+ * export a key you may export it with a pass phrase.
669
+ *
670
+ * cipher = OpenSSL::Cipher.new 'AES-256-CBC'
671
+ * pass_phrase = 'my secure pass phrase goes here'
672
+ *
673
+ * key_secure = key.export cipher, pass_phrase
674
+ *
675
+ * open 'private.secure.pem', 'w' do |io|
676
+ * io.write key_secure
677
+ * end
678
+ *
679
+ * OpenSSL::Cipher.ciphers returns a list of available ciphers.
680
+ *
681
+ * === Loading a Key
682
+ *
683
+ * A key can also be loaded from a file.
684
+ *
685
+ * key2 = OpenSSL::PKey::RSA.new File.read 'private_key.pem'
686
+ * key2.public? # => true
687
+ * key2.private? # => true
688
+ *
689
+ * or
690
+ *
691
+ * key3 = OpenSSL::PKey::RSA.new File.read 'public_key.pem'
692
+ * key3.public? # => true
693
+ * key3.private? # => false
694
+ *
695
+ * === Loading an Encrypted Key
696
+ *
697
+ * OpenSSL will prompt you for your pass phrase when loading an encrypted key.
698
+ * If you will not be able to type in the pass phrase you may provide it when
699
+ * loading the key:
700
+ *
701
+ * key4_pem = File.read 'private.secure.pem'
702
+ * pass_phrase = 'my secure pass phrase goes here'
703
+ * key4 = OpenSSL::PKey::RSA.new key4_pem, pass_phrase
704
+ *
705
+ * == RSA Encryption
706
+ *
707
+ * RSA provides encryption and decryption using the public and private keys.
708
+ * You can use a variety of padding methods depending upon the intended use of
709
+ * encrypted data.
710
+ *
711
+ * === Encryption & Decryption
712
+ *
713
+ * Asymmetric public/private key encryption is slow and victim to attack in
714
+ * cases where it is used without padding or directly to encrypt larger chunks
715
+ * of data. Typical use cases for RSA encryption involve "wrapping" a symmetric
716
+ * key with the public key of the recipient who would "unwrap" that symmetric
717
+ * key again using their private key.
718
+ * The following illustrates a simplified example of such a key transport
719
+ * scheme. It shouldn't be used in practice, though, standardized protocols
720
+ * should always be preferred.
721
+ *
722
+ * wrapped_key = key.public_encrypt key
723
+ *
724
+ * A symmetric key encrypted with the public key can only be decrypted with
725
+ * the corresponding private key of the recipient.
726
+ *
727
+ * original_key = key.private_decrypt wrapped_key
728
+ *
729
+ * By default PKCS#1 padding will be used, but it is also possible to use
730
+ * other forms of padding, see PKey::RSA for further details.
731
+ *
732
+ * === Signatures
733
+ *
734
+ * Using "private_encrypt" to encrypt some data with the private key is
735
+ * equivalent to applying a digital signature to the data. A verifying
736
+ * party may validate the signature by comparing the result of decrypting
737
+ * the signature with "public_decrypt" to the original data. However,
738
+ * OpenSSL::PKey already has methods "sign" and "verify" that handle
739
+ * digital signatures in a standardized way - "private_encrypt" and
740
+ * "public_decrypt" shouldn't be used in practice.
741
+ *
742
+ * To sign a document, a cryptographically secure hash of the document is
743
+ * computed first, which is then signed using the private key.
744
+ *
745
+ * signature = key.sign 'SHA256', document
746
+ *
747
+ * To validate the signature, again a hash of the document is computed and
748
+ * the signature is decrypted using the public key. The result is then
749
+ * compared to the hash just computed, if they are equal the signature was
750
+ * valid.
751
+ *
752
+ * if key.verify 'SHA256', signature, document
753
+ * puts 'Valid'
754
+ * else
755
+ * puts 'Invalid'
756
+ * end
757
+ *
758
+ * == PBKDF2 Password-based Encryption
759
+ *
760
+ * If supported by the underlying OpenSSL version used, Password-based
761
+ * Encryption should use the features of PKCS5. If not supported or if
762
+ * required by legacy applications, the older, less secure methods specified
763
+ * in RFC 2898 are also supported (see below).
764
+ *
765
+ * PKCS5 supports PBKDF2 as it was specified in PKCS#5
766
+ * v2.0[http://www.rsa.com/rsalabs/node.asp?id=2127]. It still uses a
767
+ * password, a salt, and additionally a number of iterations that will
768
+ * slow the key derivation process down. The slower this is, the more work
769
+ * it requires being able to brute-force the resulting key.
770
+ *
771
+ * === Encryption
772
+ *
773
+ * The strategy is to first instantiate a Cipher for encryption, and
774
+ * then to generate a random IV plus a key derived from the password
775
+ * using PBKDF2. PKCS #5 v2.0 recommends at least 8 bytes for the salt,
776
+ * the number of iterations largely depends on the hardware being used.
777
+ *
778
+ * cipher = OpenSSL::Cipher.new 'AES-256-CBC'
779
+ * cipher.encrypt
780
+ * iv = cipher.random_iv
781
+ *
782
+ * pwd = 'some hopefully not to easily guessable password'
783
+ * salt = OpenSSL::Random.random_bytes 16
784
+ * iter = 20000
785
+ * key_len = cipher.key_len
786
+ * digest = OpenSSL::Digest.new('SHA256')
787
+ *
788
+ * key = OpenSSL::PKCS5.pbkdf2_hmac(pwd, salt, iter, key_len, digest)
789
+ * cipher.key = key
790
+ *
791
+ * Now encrypt the data:
792
+ *
793
+ * encrypted = cipher.update document
794
+ * encrypted << cipher.final
795
+ *
796
+ * === Decryption
797
+ *
798
+ * Use the same steps as before to derive the symmetric AES key, this time
799
+ * setting the Cipher up for decryption.
800
+ *
801
+ * cipher = OpenSSL::Cipher.new 'AES-256-CBC'
802
+ * cipher.decrypt
803
+ * cipher.iv = iv # the one generated with #random_iv
804
+ *
805
+ * pwd = 'some hopefully not to easily guessable password'
806
+ * salt = ... # the one generated above
807
+ * iter = 20000
808
+ * key_len = cipher.key_len
809
+ * digest = OpenSSL::Digest.new('SHA256')
810
+ *
811
+ * key = OpenSSL::PKCS5.pbkdf2_hmac(pwd, salt, iter, key_len, digest)
812
+ * cipher.key = key
813
+ *
814
+ * Now decrypt the data:
815
+ *
816
+ * decrypted = cipher.update encrypted
817
+ * decrypted << cipher.final
818
+ *
819
+ * == PKCS #5 Password-based Encryption
820
+ *
821
+ * PKCS #5 is a password-based encryption standard documented at
822
+ * RFC2898[http://www.ietf.org/rfc/rfc2898.txt]. It allows a short password or
823
+ * passphrase to be used to create a secure encryption key. If possible, PBKDF2
824
+ * as described above should be used if the circumstances allow it.
825
+ *
826
+ * PKCS #5 uses a Cipher, a pass phrase and a salt to generate an encryption
827
+ * key.
828
+ *
829
+ * pass_phrase = 'my secure pass phrase goes here'
830
+ * salt = '8 octets'
831
+ *
832
+ * === Encryption
833
+ *
834
+ * First set up the cipher for encryption
835
+ *
836
+ * encryptor = OpenSSL::Cipher.new 'AES-256-CBC'
837
+ * encryptor.encrypt
838
+ * encryptor.pkcs5_keyivgen pass_phrase, salt
839
+ *
840
+ * Then pass the data you want to encrypt through
841
+ *
842
+ * encrypted = encryptor.update 'top secret document'
843
+ * encrypted << encryptor.final
844
+ *
845
+ * === Decryption
846
+ *
847
+ * Use a new Cipher instance set up for decryption
848
+ *
849
+ * decryptor = OpenSSL::Cipher.new 'AES-256-CBC'
850
+ * decryptor.decrypt
851
+ * decryptor.pkcs5_keyivgen pass_phrase, salt
852
+ *
853
+ * Then pass the data you want to decrypt through
854
+ *
855
+ * plain = decryptor.update encrypted
856
+ * plain << decryptor.final
857
+ *
858
+ * == X509 Certificates
859
+ *
860
+ * === Creating a Certificate
861
+ *
862
+ * This example creates a self-signed certificate using an RSA key and a SHA1
863
+ * signature.
864
+ *
865
+ * key = OpenSSL::PKey::RSA.new 2048
866
+ * name = OpenSSL::X509::Name.parse '/CN=nobody/DC=example'
867
+ *
868
+ * cert = OpenSSL::X509::Certificate.new
869
+ * cert.version = 2
870
+ * cert.serial = 0
871
+ * cert.not_before = Time.now
872
+ * cert.not_after = Time.now + 3600
873
+ *
874
+ * cert.public_key = key.public_key
875
+ * cert.subject = name
876
+ *
877
+ * === Certificate Extensions
878
+ *
879
+ * You can add extensions to the certificate with
880
+ * OpenSSL::SSL::ExtensionFactory to indicate the purpose of the certificate.
881
+ *
882
+ * extension_factory = OpenSSL::X509::ExtensionFactory.new nil, cert
883
+ *
884
+ * cert.add_extension \
885
+ * extension_factory.create_extension('basicConstraints', 'CA:FALSE', true)
886
+ *
887
+ * cert.add_extension \
888
+ * extension_factory.create_extension(
889
+ * 'keyUsage', 'keyEncipherment,dataEncipherment,digitalSignature')
890
+ *
891
+ * cert.add_extension \
892
+ * extension_factory.create_extension('subjectKeyIdentifier', 'hash')
893
+ *
894
+ * The list of supported extensions (and in some cases their possible values)
895
+ * can be derived from the "objects.h" file in the OpenSSL source code.
896
+ *
897
+ * === Signing a Certificate
898
+ *
899
+ * To sign a certificate set the issuer and use OpenSSL::X509::Certificate#sign
900
+ * with a digest algorithm. This creates a self-signed cert because we're using
901
+ * the same name and key to sign the certificate as was used to create the
902
+ * certificate.
903
+ *
904
+ * cert.issuer = name
905
+ * cert.sign key, OpenSSL::Digest.new('SHA1')
906
+ *
907
+ * open 'certificate.pem', 'w' do |io| io.write cert.to_pem end
908
+ *
909
+ * === Loading a Certificate
910
+ *
911
+ * Like a key, a cert can also be loaded from a file.
912
+ *
913
+ * cert2 = OpenSSL::X509::Certificate.new File.read 'certificate.pem'
914
+ *
915
+ * === Verifying a Certificate
916
+ *
917
+ * Certificate#verify will return true when a certificate was signed with the
918
+ * given public key.
919
+ *
920
+ * raise 'certificate can not be verified' unless cert2.verify key
921
+ *
922
+ * == Certificate Authority
923
+ *
924
+ * A certificate authority (CA) is a trusted third party that allows you to
925
+ * verify the ownership of unknown certificates. The CA issues key signatures
926
+ * that indicate it trusts the user of that key. A user encountering the key
927
+ * can verify the signature by using the CA's public key.
928
+ *
929
+ * === CA Key
930
+ *
931
+ * CA keys are valuable, so we encrypt and save it to disk and make sure it is
932
+ * not readable by other users.
933
+ *
934
+ * ca_key = OpenSSL::PKey::RSA.new 2048
935
+ * pass_phrase = 'my secure pass phrase goes here'
936
+ *
937
+ * cipher = OpenSSL::Cipher.new 'AES-256-CBC'
938
+ *
939
+ * open 'ca_key.pem', 'w', 0400 do |io|
940
+ * io.write ca_key.export(cipher, pass_phrase)
941
+ * end
942
+ *
943
+ * === CA Certificate
944
+ *
945
+ * A CA certificate is created the same way we created a certificate above, but
946
+ * with different extensions.
947
+ *
948
+ * ca_name = OpenSSL::X509::Name.parse '/CN=ca/DC=example'
949
+ *
950
+ * ca_cert = OpenSSL::X509::Certificate.new
951
+ * ca_cert.serial = 0
952
+ * ca_cert.version = 2
953
+ * ca_cert.not_before = Time.now
954
+ * ca_cert.not_after = Time.now + 86400
955
+ *
956
+ * ca_cert.public_key = ca_key.public_key
957
+ * ca_cert.subject = ca_name
958
+ * ca_cert.issuer = ca_name
959
+ *
960
+ * extension_factory = OpenSSL::X509::ExtensionFactory.new
961
+ * extension_factory.subject_certificate = ca_cert
962
+ * extension_factory.issuer_certificate = ca_cert
963
+ *
964
+ * ca_cert.add_extension \
965
+ * extension_factory.create_extension('subjectKeyIdentifier', 'hash')
966
+ *
967
+ * This extension indicates the CA's key may be used as a CA.
968
+ *
969
+ * ca_cert.add_extension \
970
+ * extension_factory.create_extension('basicConstraints', 'CA:TRUE', true)
971
+ *
972
+ * This extension indicates the CA's key may be used to verify signatures on
973
+ * both certificates and certificate revocations.
974
+ *
975
+ * ca_cert.add_extension \
976
+ * extension_factory.create_extension(
977
+ * 'keyUsage', 'cRLSign,keyCertSign', true)
978
+ *
979
+ * Root CA certificates are self-signed.
980
+ *
981
+ * ca_cert.sign ca_key, OpenSSL::Digest.new('SHA1')
982
+ *
983
+ * The CA certificate is saved to disk so it may be distributed to all the
984
+ * users of the keys this CA will sign.
985
+ *
986
+ * open 'ca_cert.pem', 'w' do |io|
987
+ * io.write ca_cert.to_pem
988
+ * end
989
+ *
990
+ * === Certificate Signing Request
991
+ *
992
+ * The CA signs keys through a Certificate Signing Request (CSR). The CSR
993
+ * contains the information necessary to identify the key.
994
+ *
995
+ * csr = OpenSSL::X509::Request.new
996
+ * csr.version = 0
997
+ * csr.subject = name
998
+ * csr.public_key = key.public_key
999
+ * csr.sign key, OpenSSL::Digest.new('SHA1')
1000
+ *
1001
+ * A CSR is saved to disk and sent to the CA for signing.
1002
+ *
1003
+ * open 'csr.pem', 'w' do |io|
1004
+ * io.write csr.to_pem
1005
+ * end
1006
+ *
1007
+ * === Creating a Certificate from a CSR
1008
+ *
1009
+ * Upon receiving a CSR the CA will verify it before signing it. A minimal
1010
+ * verification would be to check the CSR's signature.
1011
+ *
1012
+ * csr = OpenSSL::X509::Request.new File.read 'csr.pem'
1013
+ *
1014
+ * raise 'CSR can not be verified' unless csr.verify csr.public_key
1015
+ *
1016
+ * After verification a certificate is created, marked for various usages,
1017
+ * signed with the CA key and returned to the requester.
1018
+ *
1019
+ * csr_cert = OpenSSL::X509::Certificate.new
1020
+ * csr_cert.serial = 0
1021
+ * csr_cert.version = 2
1022
+ * csr_cert.not_before = Time.now
1023
+ * csr_cert.not_after = Time.now + 600
1024
+ *
1025
+ * csr_cert.subject = csr.subject
1026
+ * csr_cert.public_key = csr.public_key
1027
+ * csr_cert.issuer = ca_cert.subject
1028
+ *
1029
+ * extension_factory = OpenSSL::X509::ExtensionFactory.new
1030
+ * extension_factory.subject_certificate = csr_cert
1031
+ * extension_factory.issuer_certificate = ca_cert
1032
+ *
1033
+ * csr_cert.add_extension \
1034
+ * extension_factory.create_extension('basicConstraints', 'CA:FALSE')
1035
+ *
1036
+ * csr_cert.add_extension \
1037
+ * extension_factory.create_extension(
1038
+ * 'keyUsage', 'keyEncipherment,dataEncipherment,digitalSignature')
1039
+ *
1040
+ * csr_cert.add_extension \
1041
+ * extension_factory.create_extension('subjectKeyIdentifier', 'hash')
1042
+ *
1043
+ * csr_cert.sign ca_key, OpenSSL::Digest.new('SHA1')
1044
+ *
1045
+ * open 'csr_cert.pem', 'w' do |io|
1046
+ * io.write csr_cert.to_pem
1047
+ * end
1048
+ *
1049
+ * == SSL and TLS Connections
1050
+ *
1051
+ * Using our created key and certificate we can create an SSL or TLS connection.
1052
+ * An SSLContext is used to set up an SSL session.
1053
+ *
1054
+ * context = OpenSSL::SSL::SSLContext.new
1055
+ *
1056
+ * === SSL Server
1057
+ *
1058
+ * An SSL server requires the certificate and private key to communicate
1059
+ * securely with its clients:
1060
+ *
1061
+ * context.cert = cert
1062
+ * context.key = key
1063
+ *
1064
+ * Then create an SSLServer with a TCP server socket and the context. Use the
1065
+ * SSLServer like an ordinary TCP server.
1066
+ *
1067
+ * require 'socket'
1068
+ *
1069
+ * tcp_server = TCPServer.new 5000
1070
+ * ssl_server = OpenSSL::SSL::SSLServer.new tcp_server, context
1071
+ *
1072
+ * loop do
1073
+ * ssl_connection = ssl_server.accept
1074
+ *
1075
+ * data = connection.gets
1076
+ *
1077
+ * response = "I got #{data.dump}"
1078
+ * puts response
1079
+ *
1080
+ * connection.puts "I got #{data.dump}"
1081
+ * connection.close
1082
+ * end
1083
+ *
1084
+ * === SSL client
1085
+ *
1086
+ * An SSL client is created with a TCP socket and the context.
1087
+ * SSLSocket#connect must be called to initiate the SSL handshake and start
1088
+ * encryption. A key and certificate are not required for the client socket.
1089
+ *
1090
+ * Note that SSLSocket#close doesn't close the underlying socket by default. Set
1091
+ * SSLSocket#sync_close to true if you want.
1092
+ *
1093
+ * require 'socket'
1094
+ *
1095
+ * tcp_socket = TCPSocket.new 'localhost', 5000
1096
+ * ssl_client = OpenSSL::SSL::SSLSocket.new tcp_socket, context
1097
+ * ssl_client.sync_close = true
1098
+ * ssl_client.connect
1099
+ *
1100
+ * ssl_client.puts "hello server!"
1101
+ * puts ssl_client.gets
1102
+ *
1103
+ * ssl_client.close # shutdown the TLS connection and close tcp_socket
1104
+ *
1105
+ * === Peer Verification
1106
+ *
1107
+ * An unverified SSL connection does not provide much security. For enhanced
1108
+ * security the client or server can verify the certificate of its peer.
1109
+ *
1110
+ * The client can be modified to verify the server's certificate against the
1111
+ * certificate authority's certificate:
1112
+ *
1113
+ * context.ca_file = 'ca_cert.pem'
1114
+ * context.verify_mode = OpenSSL::SSL::VERIFY_PEER
1115
+ *
1116
+ * require 'socket'
1117
+ *
1118
+ * tcp_socket = TCPSocket.new 'localhost', 5000
1119
+ * ssl_client = OpenSSL::SSL::SSLSocket.new tcp_socket, context
1120
+ * ssl_client.connect
1121
+ *
1122
+ * ssl_client.puts "hello server!"
1123
+ * puts ssl_client.gets
1124
+ *
1125
+ * If the server certificate is invalid or <tt>context.ca_file</tt> is not set
1126
+ * when verifying peers an OpenSSL::SSL::SSLError will be raised.
1127
+ *
1128
+ */
1129
+ void
1130
+ Init_openssl(void)
1131
+ {
1132
+ #if HAVE_RB_EXT_RACTOR_SAFE
1133
+ rb_ext_ractor_safe(true);
1134
+ #endif
1135
+
1136
+ #undef rb_intern
1137
+ /*
1138
+ * Init timezone info
1139
+ */
1140
+ #if 0
1141
+ tzset();
1142
+ #endif
1143
+
1144
+ /*
1145
+ * Init all digests, ciphers
1146
+ */
1147
+ #if !defined(LIBRESSL_VERSION_NUMBER) && OPENSSL_VERSION_NUMBER >= 0x10100000
1148
+ if (!OPENSSL_init_ssl(0, NULL))
1149
+ rb_raise(rb_eRuntimeError, "OPENSSL_init_ssl");
1150
+ #else
1151
+ OpenSSL_add_ssl_algorithms();
1152
+ OpenSSL_add_all_algorithms();
1153
+ ERR_load_crypto_strings();
1154
+ SSL_load_error_strings();
1155
+ #endif
1156
+
1157
+ /*
1158
+ * Init main module
1159
+ */
1160
+ mOSSL = rb_define_module("OpenSSL");
1161
+ rb_global_variable(&mOSSL);
1162
+ rb_define_singleton_method(mOSSL, "fixed_length_secure_compare", ossl_crypto_fixed_length_secure_compare, 2);
1163
+
1164
+ /*
1165
+ * Version of OpenSSL the ruby OpenSSL extension was built with
1166
+ */
1167
+ rb_define_const(mOSSL, "OPENSSL_VERSION", rb_str_new2(OPENSSL_VERSION_TEXT));
1168
+
1169
+ /*
1170
+ * Version of OpenSSL the ruby OpenSSL extension is running with
1171
+ */
1172
+ #if !defined(LIBRESSL_VERSION_NUMBER) && OPENSSL_VERSION_NUMBER >= 0x10100000
1173
+ rb_define_const(mOSSL, "OPENSSL_LIBRARY_VERSION", rb_str_new2(OpenSSL_version(OPENSSL_VERSION)));
1174
+ #else
1175
+ rb_define_const(mOSSL, "OPENSSL_LIBRARY_VERSION", rb_str_new2(SSLeay_version(SSLEAY_VERSION)));
1176
+ #endif
1177
+
1178
+ /*
1179
+ * Version number of OpenSSL the ruby OpenSSL extension was built with
1180
+ * (base 16)
1181
+ */
1182
+ rb_define_const(mOSSL, "OPENSSL_VERSION_NUMBER", INT2NUM(OPENSSL_VERSION_NUMBER));
1183
+
1184
+ /*
1185
+ * Boolean indicating whether OpenSSL is FIPS-capable or not
1186
+ */
1187
+ rb_define_const(mOSSL, "OPENSSL_FIPS",
1188
+ #ifdef OPENSSL_FIPS
1189
+ Qtrue
1190
+ #else
1191
+ Qfalse
1192
+ #endif
1193
+ );
1194
+
1195
+ rb_define_module_function(mOSSL, "fips_mode", ossl_fips_mode_get, 0);
1196
+ rb_define_module_function(mOSSL, "fips_mode=", ossl_fips_mode_set, 1);
1197
+
1198
+ /*
1199
+ * Generic error,
1200
+ * common for all classes under OpenSSL module
1201
+ */
1202
+ eOSSLError = rb_define_class_under(mOSSL,"OpenSSLError",rb_eStandardError);
1203
+ rb_global_variable(&eOSSLError);
1204
+
1205
+ /*
1206
+ * Init debug core
1207
+ */
1208
+ dOSSL = Qfalse;
1209
+ rb_global_variable(&dOSSL);
1210
+
1211
+ rb_define_module_function(mOSSL, "debug", ossl_debug_get, 0);
1212
+ rb_define_module_function(mOSSL, "debug=", ossl_debug_set, 1);
1213
+ rb_define_module_function(mOSSL, "errors", ossl_get_errors, 0);
1214
+
1215
+ /*
1216
+ * Get ID of to_der
1217
+ */
1218
+ ossl_s_to_der = rb_intern("to_der");
1219
+
1220
+ #if !defined(HAVE_OPENSSL_110_THREADING_API)
1221
+ Init_ossl_locks();
1222
+ #endif
1223
+
1224
+ /*
1225
+ * Init components
1226
+ */
1227
+ Init_ossl_bn();
1228
+ Init_ossl_cipher();
1229
+ Init_ossl_config();
1230
+ Init_ossl_digest();
1231
+ Init_ossl_hmac();
1232
+ Init_ossl_ns_spki();
1233
+ Init_ossl_pkcs12();
1234
+ Init_ossl_pkcs7();
1235
+ Init_ossl_pkey();
1236
+ Init_ossl_rand();
1237
+ Init_ossl_ssl();
1238
+ #ifndef OPENSSL_NO_TS
1239
+ Init_ossl_ts();
1240
+ #endif
1241
+ Init_ossl_x509();
1242
+ Init_ossl_ocsp();
1243
+ Init_ossl_engine();
1244
+ Init_ossl_asn1();
1245
+ Init_ossl_kdf();
1246
+
1247
+ #if defined(OSSL_DEBUG)
1248
+ /*
1249
+ * For debugging Ruby/OpenSSL. Enable only when built with --enable-debug
1250
+ */
1251
+ #if !defined(LIBRESSL_VERSION_NUMBER) && \
1252
+ (OPENSSL_VERSION_NUMBER >= 0x10100000 && !defined(OPENSSL_NO_CRYPTO_MDEBUG) || \
1253
+ defined(CRYPTO_malloc_debug_init))
1254
+ rb_define_module_function(mOSSL, "mem_check_start", mem_check_start, 0);
1255
+ rb_define_module_function(mOSSL, "print_mem_leaks", print_mem_leaks, 0);
1256
+
1257
+ #if defined(CRYPTO_malloc_debug_init) /* <= 1.0.2 */
1258
+ CRYPTO_malloc_debug_init();
1259
+ #endif
1260
+
1261
+ #if defined(V_CRYPTO_MDEBUG_ALL) /* <= 1.0.2 */
1262
+ CRYPTO_set_mem_debug_options(V_CRYPTO_MDEBUG_ALL);
1263
+ #endif
1264
+
1265
+ #if OPENSSL_VERSION_NUMBER < 0x10100000 /* <= 1.0.2 */
1266
+ {
1267
+ int i;
1268
+ /*
1269
+ * See crypto/ex_data.c; call def_get_class() immediately to avoid
1270
+ * allocations. 15 is the maximum number that is used as the class index
1271
+ * in OpenSSL 1.0.2.
1272
+ */
1273
+ for (i = 0; i <= 15; i++) {
1274
+ if (CRYPTO_get_ex_new_index(i, 0, (void *)"ossl-mdebug-dummy", 0, 0, 0) < 0)
1275
+ rb_raise(rb_eRuntimeError, "CRYPTO_get_ex_new_index for "
1276
+ "class index %d failed", i);
1277
+ }
1278
+ }
1279
+ #endif
1280
+ #endif
1281
+ #endif
1282
+ }