zig_example 0.3.0 → 0.3.1

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