openssl-custom 2.2.2

Sign up to get free protection for your applications and to get access to all the features.
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
+ }