rubysl-openssl 1.0.2 → 2.0.0

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 (74) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +5 -6
  3. data/ext/rubysl/openssl/.gitignore +3 -0
  4. data/ext/rubysl/openssl/deprecation.rb +21 -0
  5. data/ext/rubysl/openssl/extconf.rb +45 -32
  6. data/ext/rubysl/openssl/openssl_missing.c +20 -7
  7. data/ext/rubysl/openssl/openssl_missing.h +22 -15
  8. data/ext/rubysl/openssl/ossl.c +610 -61
  9. data/ext/rubysl/openssl/ossl.h +31 -17
  10. data/ext/rubysl/openssl/ossl_asn1.c +974 -183
  11. data/ext/rubysl/openssl/ossl_asn1.h +3 -3
  12. data/ext/rubysl/openssl/ossl_bio.c +4 -3
  13. data/ext/rubysl/openssl/ossl_bio.h +1 -1
  14. data/ext/rubysl/openssl/ossl_bn.c +32 -28
  15. data/ext/rubysl/openssl/ossl_bn.h +1 -1
  16. data/ext/rubysl/openssl/ossl_cipher.c +494 -93
  17. data/ext/rubysl/openssl/ossl_cipher.h +1 -1
  18. data/ext/rubysl/openssl/ossl_config.c +4 -5
  19. data/ext/rubysl/openssl/ossl_config.h +1 -1
  20. data/ext/rubysl/openssl/ossl_digest.c +206 -24
  21. data/ext/rubysl/openssl/ossl_digest.h +1 -1
  22. data/ext/rubysl/openssl/ossl_engine.c +48 -26
  23. data/ext/rubysl/openssl/ossl_engine.h +1 -1
  24. data/ext/rubysl/openssl/ossl_hmac.c +40 -38
  25. data/ext/rubysl/openssl/ossl_hmac.h +1 -1
  26. data/ext/rubysl/openssl/ossl_ns_spki.c +157 -25
  27. data/ext/rubysl/openssl/ossl_ns_spki.h +1 -1
  28. data/ext/rubysl/openssl/ossl_ocsp.c +57 -40
  29. data/ext/rubysl/openssl/ossl_ocsp.h +1 -1
  30. data/ext/rubysl/openssl/ossl_pkcs12.c +15 -13
  31. data/ext/rubysl/openssl/ossl_pkcs12.h +1 -1
  32. data/ext/rubysl/openssl/ossl_pkcs5.c +108 -18
  33. data/ext/rubysl/openssl/ossl_pkcs7.c +44 -37
  34. data/ext/rubysl/openssl/ossl_pkcs7.h +1 -1
  35. data/ext/rubysl/openssl/ossl_pkey.c +211 -15
  36. data/ext/rubysl/openssl/ossl_pkey.h +19 -9
  37. data/ext/rubysl/openssl/ossl_pkey_dh.c +180 -47
  38. data/ext/rubysl/openssl/ossl_pkey_dsa.c +184 -47
  39. data/ext/rubysl/openssl/ossl_pkey_ec.c +177 -93
  40. data/ext/rubysl/openssl/ossl_pkey_rsa.c +209 -102
  41. data/ext/rubysl/openssl/ossl_rand.c +15 -15
  42. data/ext/rubysl/openssl/ossl_rand.h +1 -1
  43. data/ext/rubysl/openssl/ossl_ssl.c +939 -192
  44. data/ext/rubysl/openssl/ossl_ssl.h +6 -6
  45. data/ext/rubysl/openssl/ossl_ssl_session.c +78 -62
  46. data/ext/rubysl/openssl/ossl_version.h +2 -2
  47. data/ext/rubysl/openssl/ossl_x509.c +1 -1
  48. data/ext/rubysl/openssl/ossl_x509.h +1 -1
  49. data/ext/rubysl/openssl/ossl_x509attr.c +20 -19
  50. data/ext/rubysl/openssl/ossl_x509cert.c +169 -67
  51. data/ext/rubysl/openssl/ossl_x509crl.c +41 -39
  52. data/ext/rubysl/openssl/ossl_x509ext.c +51 -38
  53. data/ext/rubysl/openssl/ossl_x509name.c +139 -29
  54. data/ext/rubysl/openssl/ossl_x509req.c +42 -40
  55. data/ext/rubysl/openssl/ossl_x509revoked.c +20 -20
  56. data/ext/rubysl/openssl/ossl_x509store.c +99 -47
  57. data/ext/rubysl/openssl/ruby_missing.h +3 -16
  58. data/lib/openssl/bn.rb +19 -19
  59. data/lib/openssl/buffering.rb +222 -14
  60. data/lib/openssl/cipher.rb +20 -20
  61. data/lib/openssl/config.rb +1 -4
  62. data/lib/openssl/digest.rb +47 -19
  63. data/lib/openssl/ssl.rb +197 -1
  64. data/lib/openssl/x509.rb +162 -1
  65. data/lib/rubysl/openssl.rb +4 -8
  66. data/lib/rubysl/openssl/version.rb +1 -1
  67. data/rubysl-openssl.gemspec +1 -2
  68. metadata +16 -34
  69. data/ext/rubysl/openssl/extconf.h +0 -50
  70. data/lib/openssl/net/ftptls.rb +0 -53
  71. data/lib/openssl/net/telnets.rb +0 -251
  72. data/lib/openssl/pkcs7.rb +0 -25
  73. data/lib/openssl/ssl-internal.rb +0 -187
  74. data/lib/openssl/x509-internal.rb +0 -153
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: d338183332a8cda316fec73620fa2da8893f5bc6
4
- data.tar.gz: 4dae53f5f838d6af04a706d1797969c271f53495
3
+ metadata.gz: 9c238a316eb62bef98b87c16d1d8ab5941315c63
4
+ data.tar.gz: 931107b12c0c7047c860edbde9e90b43dda7f2a8
5
5
  SHA512:
6
- metadata.gz: d41c80ea649fbd47426bebdecb62555cf8530ce89deed55ac04e57d20eb470a538387954ae04405c0dff0b102236551704f10625d565c069cb1fb2d6f466b231
7
- data.tar.gz: 5ac293f0e36ddd2723cce2c039ede286a34a3380f5272a1f5cf20e8e21744b26c24b217e73f8e12bc98ea4c09d062cee536f31b0142cca314e098da0a53bd6db
6
+ metadata.gz: 9bdc04ead59cae9b0cb0ccf4e5b59665e05adf53c9b3a4d2677e22f05c201918521db924152b6050549f15d2adb519ced8ac937ac70455750d2e87700363d1bc
7
+ data.tar.gz: 33fde93ed4381c5a0269ce877fdac55a24466128d674201b50d9b9303345876ca5aa59e097c9bf22867b842dc2b961db7ad079bf283234854a9bfee82c21bf31
@@ -1,8 +1,7 @@
1
1
  language: ruby
2
- before_install:
3
- - gem update --system
4
- - gem --version
5
- - gem install rubysl-bundler
6
- script: bundle exec mspec spec
2
+ env:
3
+ - RUBYLIB=lib
4
+ script: bundle exec mspec
7
5
  rvm:
8
- - rbx-nightly-18mode
6
+ - 1.9.3
7
+ - rbx-nightly-19mode
@@ -0,0 +1,3 @@
1
+ extconf.h
2
+ mkmf.log
3
+ Makefile
@@ -0,0 +1,21 @@
1
+ module OpenSSL
2
+ def self.deprecated_warning_flag
3
+ unless flag = (@deprecated_warning_flag ||= nil)
4
+ if try_compile("", flag = "-Werror=deprecated-declarations")
5
+ if with_config("broken-apple-openssl")
6
+ flag = "-Wno-deprecated-declarations"
7
+ end
8
+ $warnflags << " #{flag}"
9
+ else
10
+ flag = ""
11
+ end
12
+ @deprecated_warning_flag = flag
13
+ end
14
+ flag
15
+ end
16
+
17
+ def self.check_func(func, header)
18
+ have_func(func, header, deprecated_warning_flag) and
19
+ have_header(header, nil, deprecated_warning_flag)
20
+ end
21
+ end
@@ -1,3 +1,4 @@
1
+ # -*- coding: us-ascii -*-
1
2
  =begin
2
3
  = $RCSfile$ -- Generator for Makefile
3
4
 
@@ -11,61 +12,59 @@
11
12
  (See the file 'LICENCE'.)
12
13
 
13
14
  = Version
14
- $Id: extconf.rb 32234 2011-06-26 08:58:06Z shyouhei $
15
+ $Id$
15
16
  =end
16
17
 
17
18
  require "mkmf"
19
+ require File.expand_path('../deprecation', __FILE__)
18
20
 
19
21
  dir_config("openssl")
20
22
  dir_config("kerberos")
21
23
 
22
- message "=== OpenSSL for Ruby configurator ===\n"
24
+ Logging::message "=== OpenSSL for Ruby configurator ===\n"
23
25
 
24
26
  ##
25
- # Adds -Wall -DOSSL_DEBUG for compilation and some more targets when GCC is used
27
+ # Adds -DOSSL_DEBUG for compilation and some more targets when GCC is used
26
28
  # To turn it on, use: --with-debug or --enable-debug
27
29
  #
28
30
  if with_config("debug") or enable_config("debug")
29
31
  $defs.push("-DOSSL_DEBUG") unless $defs.include? "-DOSSL_DEBUG"
30
-
31
- if /gcc/ =~ CONFIG["CC"]
32
- $CPPFLAGS += " -Wall" unless $CPPFLAGS.split.include? "-Wall"
33
- end
34
32
  end
35
33
 
36
34
  # Nothing we can do about these problems.
37
35
  $CPPFLAGS += " -Wno-deprecated-declarations -Wno-pointer-sign"
38
36
 
39
- message "=== Checking for system dependent stuff... ===\n"
37
+ Logging::message "=== Checking for system dependent stuff... ===\n"
40
38
  have_library("nsl", "t_open")
41
39
  have_library("socket", "socket")
42
40
  have_header("assert.h")
43
41
 
44
- message "=== Checking for required stuff... ===\n"
42
+ Logging::message "=== Checking for required stuff... ===\n"
45
43
  if $mingw
46
44
  have_library("wsock32")
47
45
  have_library("gdi32")
48
46
  end
49
- result = have_header("openssl/ssl.h")
50
- result &&= %w[crypto libeay32].any? {|lib| have_library(lib, "OpenSSL_add_all_digests")}
51
- result &&= %w[ssl ssleay32].any? {|lib| have_library(lib, "SSL_library_init")}
52
- if !result
53
- unless pkg_config("openssl") and have_header("openssl/ssl.h")
54
- message "=== Checking for required stuff failed. ===\n"
55
- message "Makefile wasn't created. Fix the errors above.\n"
47
+
48
+ result = pkg_config("openssl") && have_header("openssl/ssl.h")
49
+
50
+ unless result
51
+ result = have_header("openssl/ssl.h")
52
+ result &&= %w[crypto libeay32].any? {|lib| have_library(lib, "OpenSSL_add_all_digests")}
53
+ result &&= %w[ssl ssleay32].any? {|lib| have_library(lib, "SSL_library_init")}
54
+ unless result
55
+ Logging::message "=== Checking for required stuff failed. ===\n"
56
+ Logging::message "Makefile wasn't created. Fix the errors above.\n"
56
57
  exit 1
57
58
  end
58
59
  end
59
60
 
60
61
  unless have_header("openssl/conf_api.h")
61
- message "OpenSSL 0.9.6 or later required.\n"
62
- exit 1
62
+ raise "OpenSSL 0.9.6 or later required."
63
63
  end
64
64
 
65
- %w"rb_str_set_len rb_block_call".each {|func| have_func(func, "ruby.h")}
66
-
67
- message "=== Checking for OpenSSL features... ===\n"
65
+ Logging::message "=== Checking for OpenSSL features... ===\n"
68
66
  have_func("ERR_peek_last_error")
67
+ have_func("ASN1_put_eoc")
69
68
  have_func("BN_mod_add")
70
69
  have_func("BN_mod_sqr")
71
70
  have_func("BN_mod_sub")
@@ -99,13 +98,18 @@ have_func("X509_STORE_get_ex_data")
99
98
  have_func("X509_STORE_set_ex_data")
100
99
  have_func("OBJ_NAME_do_all_sorted")
101
100
  have_func("SSL_SESSION_get_id")
101
+ have_func("SSL_SESSION_cmp")
102
102
  have_func("OPENSSL_cleanse")
103
- if try_compile("#define FOO(...) foo(__VA_ARGS__)\n int x(){FOO(1);FOO(1,2);FOO(1,2,3);}\n")
104
- $defs.push("-DHAVE_VA_ARGS_MACRO")
105
- end
106
103
  have_func("SSLv2_method")
107
104
  have_func("SSLv2_server_method")
108
105
  have_func("SSLv2_client_method")
106
+ have_func("TLSv1_1_method")
107
+ have_func("TLSv1_1_server_method")
108
+ have_func("TLSv1_1_client_method")
109
+ have_func("TLSv1_2_method")
110
+ have_func("TLSv1_2_server_method")
111
+ have_func("TLSv1_2_client_method")
112
+ have_macro("OPENSSL_NPN_NEGOTIATED", ['openssl/ssl.h']) && $defs.push("-DHAVE_OPENSSL_NPN_NEGOTIATED")
109
113
  unless have_func("SSL_set_tlsext_host_name", ['openssl/ssl.h'])
110
114
  have_macro("SSL_set_tlsext_host_name", ['openssl/ssl.h']) && $defs.push("-DHAVE_SSL_SET_TLSEXT_HOST_NAME")
111
115
  end
@@ -116,6 +120,7 @@ if have_header("openssl/engine.h")
116
120
  have_func("ENGINE_get_digest")
117
121
  have_func("ENGINE_get_cipher")
118
122
  have_func("ENGINE_cleanup")
123
+ have_func("ENGINE_load_dynamic")
119
124
  have_func("ENGINE_load_4758cca")
120
125
  have_func("ENGINE_load_aep")
121
126
  have_func("ENGINE_load_atalla")
@@ -124,21 +129,29 @@ if have_header("openssl/engine.h")
124
129
  have_func("ENGINE_load_nuron")
125
130
  have_func("ENGINE_load_sureware")
126
131
  have_func("ENGINE_load_ubsec")
132
+ have_func("ENGINE_load_padlock")
133
+ have_func("ENGINE_load_capi")
134
+ have_func("ENGINE_load_gmp")
135
+ have_func("ENGINE_load_gost")
136
+ have_func("ENGINE_load_cryptodev")
137
+ have_func("ENGINE_load_aesni")
127
138
  end
128
- if try_compile(<<SRC)
129
- #include <openssl/opensslv.h>
130
- #if OPENSSL_VERSION_NUMBER < 0x00907000L
131
- # error "OpenSSL version is less than 0.9.7."
132
- #endif
133
- SRC
139
+ have_func("DH_generate_parameters_ex")
140
+ have_func("DSA_generate_parameters_ex")
141
+ have_func("RSA_generate_key_ex")
142
+ if checking_for('OpenSSL version is 0.9.7 or later') {
143
+ try_static_assert('OPENSSL_VERSION_NUMBER >= 0x00907000L', 'openssl/opensslv.h')
144
+ }
134
145
  have_header("openssl/ocsp.h")
135
146
  end
136
147
  have_struct_member("EVP_CIPHER_CTX", "flags", "openssl/evp.h")
137
148
  have_struct_member("EVP_CIPHER_CTX", "engine", "openssl/evp.h")
138
149
  have_struct_member("X509_ATTRIBUTE", "single", "openssl/x509.h")
150
+ have_macro("OPENSSL_FIPS", ['openssl/opensslconf.h']) && $defs.push("-DHAVE_OPENSSL_FIPS")
151
+ have_macro("EVP_CTRL_GCM_GET_TAG", ['openssl/evp.h']) && $defs.push("-DHAVE_AUTHENTICATED_ENCRYPTION")
139
152
 
140
- message "=== Checking done. ===\n"
153
+ Logging::message "=== Checking done. ===\n"
141
154
 
142
155
  create_header
143
156
  create_makefile("openssl/openssl")
144
- message "Done.\n"
157
+ Logging::message "Done.\n"
@@ -1,5 +1,5 @@
1
1
  /*
2
- * $Id: openssl_missing.c 16467 2008-05-19 03:00:52Z knu $
2
+ * $Id$
3
3
  * 'OpenSSL for Ruby' project
4
4
  * Copyright (C) 2001-2002 Michal Rokos <m.rokos@sh.cvut.cz>
5
5
  * All rights reserved.
@@ -36,12 +36,13 @@ HMAC_CTX_copy(HMAC_CTX *out, HMAC_CTX *in)
36
36
  #endif /* NO_HMAC */
37
37
 
38
38
  #if !defined(HAVE_X509_STORE_SET_EX_DATA)
39
-
40
39
  int X509_STORE_set_ex_data(X509_STORE *str, int idx, void *data)
41
40
  {
42
41
  return CRYPTO_set_ex_data(&str->ex_data, idx, data);
43
42
  }
44
-
43
+ #endif
44
+
45
+ #if !defined(HAVE_X509_STORE_GET_EX_DATA)
45
46
  void *X509_STORE_get_ex_data(X509_STORE *str, int idx)
46
47
  {
47
48
  return CRYPTO_get_ex_data(&str->ex_data, idx);
@@ -111,7 +112,7 @@ HMAC_CTX_cleanup(HMAC_CTX *ctx)
111
112
  #endif
112
113
 
113
114
  #if !defined(HAVE_EVP_CIPHER_CTX_COPY)
114
- /*
115
+ /*
115
116
  * this function does not exist in OpenSSL yet... or ever?.
116
117
  * a future version may break this function.
117
118
  * tested on 0.9.7d.
@@ -180,12 +181,12 @@ OSSL_X509_REVOKED_cmp(const X509_REVOKED * const *a, const X509_REVOKED * const
180
181
  (ASN1_STRING *)(*a)->serialNumber,
181
182
  (ASN1_STRING *)(*b)->serialNumber));
182
183
  }
183
-
184
+
184
185
  int
185
186
  X509_CRL_add0_revoked(X509_CRL *crl, X509_REVOKED *rev)
186
187
  {
187
188
  X509_CRL_INFO *inf;
188
-
189
+
189
190
  inf = crl->crl;
190
191
  if (!inf->revoked)
191
192
  inf->revoked = sk_X509_REVOKED_new(OSSL_X509_REVOKED_cmp);
@@ -313,7 +314,7 @@ PEM_def_callback(char *buf, int num, int w, void *key)
313
314
  {
314
315
  int i,j;
315
316
  const char *prompt;
316
-
317
+
317
318
  if (key) {
318
319
  i = strlen(key);
319
320
  i = (i > num) ? num : i;
@@ -341,3 +342,15 @@ PEM_def_callback(char *buf, int num, int w, void *key)
341
342
  }
342
343
  #endif
343
344
 
345
+ #if !defined(HAVE_ASN1_PUT_EOC)
346
+ int
347
+ ASN1_put_eoc(unsigned char **pp)
348
+ {
349
+ unsigned char *p = *pp;
350
+ *p++ = 0;
351
+ *p++ = 0;
352
+ *pp = p;
353
+ return 2;
354
+ }
355
+ #endif
356
+
@@ -28,42 +28,42 @@ typedef int i2d_of_void();
28
28
 
29
29
  #if !defined(PEM_read_bio_DSAPublicKey)
30
30
  # define PEM_read_bio_DSAPublicKey(bp,x,cb,u) (DSA *)PEM_ASN1_read_bio( \
31
- (void *(*)())d2i_DSAPublicKey,PEM_STRING_DSA_PUBLIC,bp,(void **)x,cb,u)
31
+ (d2i_of_void *)d2i_DSAPublicKey,PEM_STRING_DSA_PUBLIC,(bp),(void **)(x),(cb),(u))
32
32
  #endif
33
33
 
34
34
  #if !defined(PEM_write_bio_DSAPublicKey)
35
35
  # define PEM_write_bio_DSAPublicKey(bp,x) \
36
36
  PEM_ASN1_write_bio((i2d_of_void *)i2d_DSAPublicKey,\
37
37
  PEM_STRING_DSA_PUBLIC,\
38
- bp,(char *)x, NULL, NULL, 0, NULL, NULL)
38
+ (bp),(char *)(x), NULL, NULL, 0, NULL, NULL)
39
39
  #endif
40
40
 
41
41
  #if !defined(DSAPrivateKey_dup)
42
42
  # define DSAPrivateKey_dup(dsa) (DSA *)ASN1_dup((i2d_of_void *)i2d_DSAPrivateKey, \
43
- (void *(*)())d2i_DSAPrivateKey,(void *)dsa)
43
+ (d2i_of_void *)d2i_DSAPrivateKey,(char *)(dsa))
44
44
  #endif
45
45
 
46
46
  #if !defined(DSAPublicKey_dup)
47
47
  # define DSAPublicKey_dup(dsa) (DSA *)ASN1_dup((i2d_of_void *)i2d_DSAPublicKey, \
48
- (void *(*)())d2i_DSAPublicKey,(void *)dsa)
48
+ (d2i_of_void *)d2i_DSAPublicKey,(char *)(dsa))
49
49
  #endif
50
50
 
51
51
  #if !defined(X509_REVOKED_dup)
52
52
  # define X509_REVOKED_dup(rev) (X509_REVOKED *)ASN1_dup((i2d_of_void *)i2d_X509_REVOKED, \
53
- (void *(*)())d2i_X509_REVOKED, (void *)rev)
53
+ (d2i_of_void *)d2i_X509_REVOKED, (char *)(rev))
54
54
  #endif
55
55
 
56
56
  #if !defined(PKCS7_SIGNER_INFO_dup)
57
57
  # define PKCS7_SIGNER_INFO_dup(si) (PKCS7_SIGNER_INFO *)ASN1_dup((i2d_of_void *)i2d_PKCS7_SIGNER_INFO, \
58
- (void *(*)())d2i_PKCS7_SIGNER_INFO, (void *)si)
58
+ (d2i_of_void *)d2i_PKCS7_SIGNER_INFO, (char *)(si))
59
59
  #endif
60
60
 
61
61
  #if !defined(PKCS7_RECIP_INFO_dup)
62
62
  # define PKCS7_RECIP_INFO_dup(ri) (PKCS7_RECIP_INFO *)ASN1_dup((i2d_of_void *)i2d_PKCS7_RECIP_INFO, \
63
- (void *(*)())d2i_PKCS7_RECIP_INFO, (void *)ri)
63
+ (d2i_of_void *)d2i_PKCS7_RECIP_INFO, (char *)(ri))
64
64
  #endif
65
65
 
66
- #if !defined(HAVE_EVP_MD_CTX_INIT)
66
+ #if !defined(HAVE_HMAC_CTX_INIT)
67
67
  void HMAC_CTX_init(HMAC_CTX *ctx);
68
68
  #endif
69
69
 
@@ -96,17 +96,17 @@ int EVP_CIPHER_CTX_copy(EVP_CIPHER_CTX *out, EVP_CIPHER_CTX *in);
96
96
  #endif
97
97
 
98
98
  #if !defined(HAVE_EVP_DIGESTINIT_EX)
99
- # define EVP_DigestInit_ex(ctx, md, engine) EVP_DigestInit(ctx, md)
99
+ # define EVP_DigestInit_ex(ctx, md, engine) EVP_DigestInit((ctx), (md))
100
100
  #endif
101
101
  #if !defined(HAVE_EVP_DIGESTFINAL_EX)
102
- # define EVP_DigestFinal_ex(ctx, buf, len) EVP_DigestFinal(ctx, buf, len)
102
+ # define EVP_DigestFinal_ex(ctx, buf, len) EVP_DigestFinal((ctx), (buf), (len))
103
103
  #endif
104
104
 
105
105
  #if !defined(HAVE_EVP_CIPHERINIT_EX)
106
- # define EVP_CipherInit_ex(ctx, type, impl, key, iv, enc) EVP_CipherInit(ctx, type, key, iv, enc)
106
+ # define EVP_CipherInit_ex(ctx, type, impl, key, iv, enc) EVP_CipherInit((ctx), (type), (key), (iv), (enc))
107
107
  #endif
108
108
  #if !defined(HAVE_EVP_CIPHERFINAL_EX)
109
- # define EVP_CipherFinal_ex(ctx, outm, outl) EVP_CipherFinal(ctx, outm, outl)
109
+ # define EVP_CipherFinal_ex(ctx, outm, outl) EVP_CipherFinal((ctx), (outm), (outl))
110
110
  #endif
111
111
 
112
112
  #if !defined(EVP_CIPHER_name)
@@ -118,7 +118,7 @@ int EVP_CIPHER_CTX_copy(EVP_CIPHER_CTX *out, EVP_CIPHER_CTX *in);
118
118
  #endif
119
119
 
120
120
  #if !defined(HAVE_EVP_HMAC_INIT_EX)
121
- # define HMAC_Init_ex(ctx, key, len, digest, engine) HMAC_Init(ctx, key, len, digest)
121
+ # define HMAC_Init_ex(ctx, key, len, digest, engine) HMAC_Init((ctx), (key), (len), (digest))
122
122
  #endif
123
123
 
124
124
  #if !defined(PKCS7_is_detached)
@@ -130,11 +130,14 @@ int EVP_CIPHER_CTX_copy(EVP_CIPHER_CTX *out, EVP_CIPHER_CTX *in);
130
130
  #endif
131
131
 
132
132
  #if !defined(HAVE_OPENSSL_CLEANSE)
133
- #define OPENSSL_cleanse(p, l) memset(p, 0, l)
133
+ #define OPENSSL_cleanse(p, l) memset((p), 0, (l))
134
134
  #endif
135
135
 
136
- #if !defined(HAVE_X509_STORE_SET_EX_DATA)
136
+ #if !defined(HAVE_X509_STORE_GET_EX_DATA)
137
137
  void *X509_STORE_get_ex_data(X509_STORE *str, int idx);
138
+ #endif
139
+
140
+ #if !defined(HAVE_X509_STORE_SET_EX_DATA)
138
141
  int X509_STORE_set_ex_data(X509_STORE *str, int idx, void *data);
139
142
  #endif
140
143
 
@@ -182,6 +185,10 @@ char *CONF_get1_default_config_file(void);
182
185
  int PEM_def_callback(char *buf, int num, int w, void *key);
183
186
  #endif
184
187
 
188
+ #if !defined(HAVE_ASN1_PUT_EOC)
189
+ int ASN1_put_eoc(unsigned char **pp);
190
+ #endif
191
+
185
192
  #if defined(__cplusplus)
186
193
  }
187
194
  #endif
@@ -1,5 +1,5 @@
1
1
  /*
2
- * $Id: ossl.c 28367 2010-06-21 09:18:59Z shyouhei $
2
+ * $Id$
3
3
  * 'OpenSSL for Ruby' project
4
4
  * Copyright (C) 2001-2002 Michal Rokos <m.rokos@sh.cvut.cz>
5
5
  * All rights reserved.
@@ -15,7 +15,7 @@
15
15
  * String to HEXString conversion
16
16
  */
17
17
  int
18
- string2hex(char *buf, int buf_len, char **hexbuf, int *hexbuf_len)
18
+ string2hex(const unsigned char *buf, int buf_len, char **hexbuf, int *hexbuf_len)
19
19
  {
20
20
  static const char hex[]="0123456789abcdef";
21
21
  int i, len = 2 * buf_len;
@@ -47,48 +47,53 @@ string2hex(char *buf, int buf_len, char **hexbuf, int *hexbuf_len)
47
47
  /*
48
48
  * Data Conversion
49
49
  */
50
- STACK_OF(X509) *
51
- ossl_x509_ary2sk0(VALUE ary)
52
- {
53
- STACK_OF(X509) *sk;
54
- VALUE val;
55
- X509 *x509;
56
- int i;
57
-
58
- Check_Type(ary, T_ARRAY);
59
- sk = sk_X509_new_null();
60
- if (!sk) ossl_raise(eOSSLError, NULL);
61
-
62
- for (i = 0; i < RARRAY_LEN(ary); i++) {
63
- val = rb_ary_entry(ary, i);
64
- if (!rb_obj_is_kind_of(val, cX509Cert)) {
65
- sk_X509_pop_free(sk, X509_free);
66
- ossl_raise(eOSSLError, "object not X509 cert in array");
67
- }
68
- x509 = DupX509CertPtr(val); /* NEED TO DUP */
69
- sk_X509_push(sk, x509);
70
- }
71
- return sk;
72
- }
73
-
74
- STACK_OF(X509) *
75
- ossl_protect_x509_ary2sk(VALUE ary, int *status)
76
- {
77
- return (STACK_OF(X509)*)rb_protect((VALUE(*)_((VALUE)))ossl_x509_ary2sk0,
78
- ary, status);
79
- }
80
-
81
- STACK_OF(X509) *
82
- ossl_x509_ary2sk(VALUE ary)
83
- {
84
- STACK_OF(X509) *sk;
85
- int status = 0;
86
-
87
- sk = ossl_protect_x509_ary2sk(ary, &status);
88
- if(status) rb_jump_tag(status);
89
-
90
- return sk;
50
+ #define OSSL_IMPL_ARY2SK(name, type, expected_class, dup) \
51
+ STACK_OF(type) * \
52
+ ossl_##name##_ary2sk0(VALUE ary) \
53
+ { \
54
+ STACK_OF(type) *sk; \
55
+ VALUE val; \
56
+ type *x; \
57
+ int i; \
58
+ \
59
+ Check_Type(ary, T_ARRAY); \
60
+ sk = sk_##type##_new_null(); \
61
+ if (!sk) ossl_raise(eOSSLError, NULL); \
62
+ \
63
+ for (i = 0; i < RARRAY_LEN(ary); i++) { \
64
+ val = rb_ary_entry(ary, i); \
65
+ if (!rb_obj_is_kind_of(val, expected_class)) { \
66
+ sk_##type##_pop_free(sk, type##_free); \
67
+ ossl_raise(eOSSLError, "object in array not" \
68
+ " of class ##type##"); \
69
+ } \
70
+ x = dup(val); /* NEED TO DUP */ \
71
+ sk_##type##_push(sk, x); \
72
+ } \
73
+ return sk; \
74
+ } \
75
+ \
76
+ STACK_OF(type) * \
77
+ ossl_protect_##name##_ary2sk(VALUE ary, int *status) \
78
+ { \
79
+ return (STACK_OF(type)*)rb_protect( \
80
+ (VALUE(*)_((VALUE)))ossl_##name##_ary2sk0, \
81
+ ary, \
82
+ status); \
83
+ } \
84
+ \
85
+ STACK_OF(type) * \
86
+ ossl_##name##_ary2sk(VALUE ary) \
87
+ { \
88
+ STACK_OF(type) *sk; \
89
+ int status = 0; \
90
+ \
91
+ sk = ossl_protect_##name##_ary2sk(ary, &status); \
92
+ if (status) rb_jump_tag(status); \
93
+ \
94
+ return sk; \
91
95
  }
96
+ OSSL_IMPL_ARY2SK(x509, X509, cX509Cert, DupX509CertPtr)
92
97
 
93
98
  #define OSSL_IMPL_SK2ARY(name, type) \
94
99
  VALUE \
@@ -117,6 +122,7 @@ ossl_##name##_sk2ary(STACK_OF(type) *sk) \
117
122
  }
118
123
  OSSL_IMPL_SK2ARY(x509, X509)
119
124
  OSSL_IMPL_SK2ARY(x509crl, X509_CRL)
125
+ OSSL_IMPL_SK2ARY(x509name, X509_NAME)
120
126
 
121
127
  static VALUE
122
128
  ossl_str_new(int size)
@@ -143,7 +149,7 @@ ossl_buf2str(char *buf, int len)
143
149
  */
144
150
  static VALUE
145
151
  ossl_pem_passwd_cb0(VALUE flag)
146
- {
152
+ {
147
153
  VALUE pass;
148
154
 
149
155
  pass = rb_yield(flag);
@@ -157,7 +163,7 @@ ossl_pem_passwd_cb(char *buf, int max_len, int flag, void *pwd)
157
163
  {
158
164
  int len, status = 0;
159
165
  VALUE rflag, pass;
160
-
166
+
161
167
  if (pwd || !rb_block_given_p())
162
168
  return PEM_def_callback(buf, max_len, flag, pwd);
163
169
 
@@ -169,8 +175,12 @@ ossl_pem_passwd_cb(char *buf, int max_len, int flag, void *pwd)
169
175
  */
170
176
  rflag = flag ? Qtrue : Qfalse;
171
177
  pass = rb_protect(ossl_pem_passwd_cb0, rflag, &status);
172
- if (status) return -1; /* exception was raised. */
173
- len = RSTRING_LEN(pass);
178
+ if (status) {
179
+ /* ignore an exception raised. */
180
+ rb_set_errinfo(Qnil);
181
+ return -1;
182
+ }
183
+ len = RSTRING_LENINT(pass);
174
184
  if (len < 4) { /* 4 is OpenSSL hardcoded limit */
175
185
  rb_warning("password must be longer than 4 bytes");
176
186
  continue;
@@ -192,12 +202,12 @@ int ossl_verify_cb_idx;
192
202
 
193
203
  VALUE
194
204
  ossl_call_verify_cb_proc(struct ossl_verify_cb_args *args)
195
- {
205
+ {
196
206
  return rb_funcall(args->proc, rb_intern("call"), 2,
197
207
  args->preverify_ok, args->store_ctx);
198
208
  }
199
-
200
- int
209
+
210
+ int
201
211
  ossl_verify_cb(int ok, X509_STORE_CTX *ctx)
202
212
  {
203
213
  VALUE proc, rctx, ret;
@@ -210,15 +220,23 @@ ossl_verify_cb(int ok, X509_STORE_CTX *ctx)
210
220
  if ((void*)proc == 0)
211
221
  return ok;
212
222
  if (!NIL_P(proc)) {
223
+ ret = Qfalse;
213
224
  rctx = rb_protect((VALUE(*)(VALUE))ossl_x509stctx_new,
214
225
  (VALUE)ctx, &state);
215
- ret = Qfalse;
216
- if (!state) {
226
+ if (state) {
227
+ rb_set_errinfo(Qnil);
228
+ rb_warn("StoreContext initialization failure");
229
+ }
230
+ else {
217
231
  args.proc = proc;
218
232
  args.preverify_ok = ok ? Qtrue : Qfalse;
219
233
  args.store_ctx = rctx;
220
- ret = rb_ensure(ossl_call_verify_cb_proc, (VALUE)&args,
221
- ossl_x509stctx_clear_ptr, rctx);
234
+ ret = rb_protect((VALUE(*)(VALUE))ossl_call_verify_cb_proc, (VALUE)&args, &state);
235
+ if (state) {
236
+ rb_set_errinfo(Qnil);
237
+ rb_warn("exception in verify_callback is ignored");
238
+ }
239
+ ossl_x509stctx_clear_ptr(rctx);
222
240
  }
223
241
  if (ret == Qtrue) {
224
242
  X509_STORE_CTX_set_error(ctx, X509_V_OK);
@@ -302,7 +320,7 @@ ossl_make_error(VALUE exc, const char *fmt, va_list args)
302
320
  }
303
321
  ERR_clear_error();
304
322
 
305
- if(len > BUFSIZ) len = strlen(buf);
323
+ if(len > BUFSIZ) len = rb_long2int(strlen(buf));
306
324
  return rb_exc_new(exc, buf, len);
307
325
  }
308
326
 
@@ -360,7 +378,7 @@ void
360
378
  ossl_debug(const char *fmt, ...)
361
379
  {
362
380
  va_list args;
363
-
381
+
364
382
  if (dOSSL == Qtrue) {
365
383
  fprintf(stderr, "OSSL_DEBUG: ");
366
384
  va_start(args, fmt);
@@ -393,7 +411,7 @@ ossl_debug_set(VALUE self, VALUE val)
393
411
  {
394
412
  VALUE old = dOSSL;
395
413
  dOSSL = val;
396
-
414
+
397
415
  if (old != dOSSL) {
398
416
  if (dOSSL == Qtrue) {
399
417
  CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ON);
@@ -406,6 +424,40 @@ ossl_debug_set(VALUE self, VALUE val)
406
424
  return val;
407
425
  }
408
426
 
427
+ /*
428
+ * call-seq:
429
+ * OpenSSL.fips_mode = boolean -> boolean
430
+ *
431
+ * Turns FIPS mode on or off. Turning on FIPS mode will obviously only have an
432
+ * effect for FIPS-capable installations of the OpenSSL library. Trying to do
433
+ * so otherwise will result in an error.
434
+ *
435
+ * === Examples
436
+ *
437
+ * OpenSSL.fips_mode = true # turn FIPS mode on
438
+ * OpenSSL.fips_mode = false # and off again
439
+ */
440
+ static VALUE
441
+ ossl_fips_mode_set(VALUE self, VALUE enabled)
442
+ {
443
+
444
+ #ifdef HAVE_OPENSSL_FIPS
445
+ if (RTEST(enabled)) {
446
+ int mode = FIPS_mode();
447
+ if(!mode && !FIPS_mode_set(1)) /* turning on twice leads to an error */
448
+ ossl_raise(eOSSLError, "Turning on FIPS mode failed");
449
+ } else {
450
+ if(!FIPS_mode_set(0)) /* turning off twice is OK */
451
+ ossl_raise(eOSSLError, "Turning off FIPS mode failed");
452
+ }
453
+ return enabled;
454
+ #else
455
+ if (RTEST(enabled))
456
+ ossl_raise(eOSSLError, "This version of OpenSSL does not support FIPS mode");
457
+ return enabled;
458
+ #endif
459
+ }
460
+
409
461
  /**
410
462
  * Stores locks needed for OpenSSL thread safety
411
463
  */
@@ -439,7 +491,485 @@ static void Init_ossl_locks(void)
439
491
  }
440
492
 
441
493
  /*
442
- * OSSL library init
494
+ * OpenSSL provides SSL, TLS and general purpose cryptography. It wraps the
495
+ * OpenSSL[http://www.openssl.org/] library.
496
+ *
497
+ * = Examples
498
+ *
499
+ * All examples assume you have loaded OpenSSL with:
500
+ *
501
+ * require 'openssl'
502
+ *
503
+ * These examples build atop each other. For example the key created in the
504
+ * next is used in throughout these examples.
505
+ *
506
+ * == Keys
507
+ *
508
+ * === Creating a Key
509
+ *
510
+ * This example creates a 2048 bit RSA keypair and writes it to the current
511
+ * directory.
512
+ *
513
+ * key = OpenSSL::PKey::RSA.new 2048
514
+ *
515
+ * open 'private_key.pem', 'w' do |io| io.write key.to_pem end
516
+ * open 'public_key.pem', 'w' do |io| io.write key.public_key.to_pem end
517
+ *
518
+ * === Exporting a Key
519
+ *
520
+ * Keys saved to disk without encryption are not secure as anyone who gets
521
+ * ahold of the key may use it unless it is encrypted. In order to securely
522
+ * export a key you may export it with a pass phrase.
523
+ *
524
+ * cipher = OpenSSL::Cipher.new 'AES-128-CBC'
525
+ * pass_phrase = 'my secure pass phrase goes here'
526
+ *
527
+ * key_secure = key.export cipher, pass_phrase
528
+ *
529
+ * open 'private.secure.pem', 'w' do |io|
530
+ * io.write key_secure
531
+ * end
532
+ *
533
+ * OpenSSL::Cipher.ciphers returns a list of available ciphers.
534
+ *
535
+ * === Loading a Key
536
+ *
537
+ * A key can also be loaded from a file.
538
+ *
539
+ * key2 = OpenSSL::PKey::RSA.new File.read 'private_key.pem'
540
+ * key2.public? # => true
541
+ *
542
+ * or
543
+ *
544
+ * key3 = OpenSSL::PKey::RSA.new File.read 'public_key.pem'
545
+ * key3.private? # => false
546
+ *
547
+ * === Loading an Encrypted Key
548
+ *
549
+ * OpenSSL will prompt you for your pass phrase when loading an encrypted key.
550
+ * If you will not be able to type in the pass phrase you may provide it when
551
+ * loading the key:
552
+ *
553
+ * key4_pem = File.read 'private.secure.pem'
554
+ * key4 = OpenSSL::PKey::RSA.new key4_pem, pass_phrase
555
+ *
556
+ * == RSA Encryption
557
+ *
558
+ * RSA provides encryption and decryption using the public and private keys.
559
+ * You can use a variety of padding methods depending upon the intended use of
560
+ * encrypted data.
561
+ *
562
+ * === Encryption & Decryption
563
+ *
564
+ * Asymmetric public/private key encryption is slow and victim to attack in
565
+ * cases where it is used without padding or directly to encrypt larger chunks
566
+ * of data. Typical use cases for RSA encryption involve "wrapping" a symmetric
567
+ * key with the public key of the recipient who would "unwrap" that symmetric
568
+ * key again using their private key.
569
+ * The following illustrates a simplified example of such a key transport
570
+ * scheme. It shouldn't be used in practice, though, standardized protocols
571
+ * should always be preferred.
572
+ *
573
+ * wrapped_key = key.public_encrypt key
574
+ *
575
+ * A symmetric key encrypted with the public key can only be decrypted with
576
+ * the corresponding private key of the recipient.
577
+ *
578
+ * original_key = key.private_decrypt wrapped_key
579
+ *
580
+ * By default PKCS#1 padding will be used, but it is also possible to use
581
+ * other forms of padding, see PKey::RSA for further details.
582
+ *
583
+ * === Signatures
584
+ *
585
+ * Using "private_encrypt" to encrypt some data with the private key is
586
+ * equivalent to applying a digital signature to the data. A verifying
587
+ * party may validate the signature by comparing the result of decrypting
588
+ * the signature with "public_decrypt" to the original data. However,
589
+ * OpenSSL::PKey already has methods "sign" and "verify" that handle
590
+ * digital signatures in a standardized way - "private_encrypt" and
591
+ * "public_decrypt" shouldn't be used in practice.
592
+ *
593
+ * To sign a document, a cryptographically secure hash of the document is
594
+ * computed first, which is then signed using the private key.
595
+ *
596
+ * digest = OpenSSL::Digest::SHA256.new
597
+ * signature = key.sign digest, document
598
+ *
599
+ * To validate the signature, again a hash of the document is computed and
600
+ * the signature is decrypted using the public key. The result is then
601
+ * compared to the hash just computed, if they are equal the signature was
602
+ * valid.
603
+ *
604
+ * digest = OpenSSL::Digest::SHA256.new
605
+ * if key.verify digest, signature, document
606
+ * puts 'Valid'
607
+ * else
608
+ * puts 'Invalid'
609
+ * end
610
+ *
611
+ * == PBKDF2 Password-based Encryption
612
+ *
613
+ * If supported by the underlying OpenSSL version used, Password-based
614
+ * Encryption should use the features of PKCS5. If not supported or if
615
+ * required by legacy applications, the older, less secure methods specified
616
+ * in RFC 2898 are also supported (see below).
617
+ *
618
+ * PKCS5 supports PBKDF2 as it was specified in PKCS#5
619
+ * v2.0[http://www.rsa.com/rsalabs/node.asp?id=2127]. It still uses a
620
+ * password, a salt, and additionally a number of iterations that will
621
+ * slow the key derivation process down. The slower this is, the more work
622
+ * it requires being able to brute-force the resulting key.
623
+ *
624
+ * === Encryption
625
+ *
626
+ * The strategy is to first instantiate a Cipher for encryption, and
627
+ * then to generate a random IV plus a key derived from the password
628
+ * using PBKDF2. PKCS #5 v2.0 recommends at least 8 bytes for the salt,
629
+ * the number of iterations largely depends on the hardware being used.
630
+ *
631
+ * cipher = OpenSSL::Cipher.new 'AES-128-CBC'
632
+ * cipher.encrypt
633
+ * iv = cipher.random_iv
634
+ *
635
+ * pwd = 'some hopefully not to easily guessable password'
636
+ * salt = OpenSSL::Random.random_bytes 16
637
+ * iter = 20000
638
+ * key_len = cipher.key_len
639
+ * digest = OpenSSL::Digest::SHA256.new
640
+ *
641
+ * key = OpenSSL::PKCS5.pbkdf2_hmac(pwd, salt, iter, key_len, digest)
642
+ * cipher.key = key
643
+ *
644
+ * Now encrypt the data:
645
+ *
646
+ * encrypted = cipher.update document
647
+ * encrypted << cipher.final
648
+ *
649
+ * === Decryption
650
+ *
651
+ * Use the same steps as before to derive the symmetric AES key, this time
652
+ * setting the Cipher up for decryption.
653
+ *
654
+ * cipher = OpenSSL::Cipher.new 'AES-128-CBC'
655
+ * cipher.decrypt
656
+ * cipher.iv = iv # the one generated with #random_iv
657
+ *
658
+ * pwd = 'some hopefully not to easily guessable password'
659
+ * salt = ... # the one generated above
660
+ * iter = 20000
661
+ * key_len = cipher.key_len
662
+ * digest = OpenSSL::Digest::SHA256.new
663
+ *
664
+ * key = OpenSSL::PKCS5.pbkdf2_hmac(pwd, salt, iter, key_len, digest)
665
+ * cipher.key = key
666
+ *
667
+ * Now decrypt the data:
668
+ *
669
+ * decrypted = cipher.update encrypted
670
+ * decrypted << cipher.final
671
+ *
672
+ * == PKCS #5 Password-based Encryption
673
+ *
674
+ * PKCS #5 is a password-based encryption standard documented at
675
+ * RFC2898[http://www.ietf.org/rfc/rfc2898.txt]. It allows a short password or
676
+ * passphrase to be used to create a secure encryption key. If possible, PBKDF2
677
+ * as described above should be used if the circumstances allow it.
678
+ *
679
+ * PKCS #5 uses a Cipher, a pass phrase and a salt to generate an encryption
680
+ * key.
681
+ *
682
+ * pass_phrase = 'my secure pass phrase goes here'
683
+ * salt = '8 octets'
684
+ *
685
+ * === Encryption
686
+ *
687
+ * First set up the cipher for encryption
688
+ *
689
+ * encrypter = OpenSSL::Cipher.new 'AES-128-CBC'
690
+ * encrypter.encrypt
691
+ * encrypter.pkcs5_keyivgen pass_phrase, salt
692
+ *
693
+ * Then pass the data you want to encrypt through
694
+ *
695
+ * encrypted = encrypter.update 'top secret document'
696
+ * encrypted << encrypter.final
697
+ *
698
+ * === Decryption
699
+ *
700
+ * Use a new Cipher instance set up for decryption
701
+ *
702
+ * decrypter = OpenSSL::Cipher.new 'AES-128-CBC'
703
+ * decrypter.decrypt
704
+ * decrypter.pkcs5_keyivgen pass_phrase, salt
705
+ *
706
+ * Then pass the data you want to decrypt through
707
+ *
708
+ * plain = decrypter.update encrypted
709
+ * plain << decrypter.final
710
+ *
711
+ * == X509 Certificates
712
+ *
713
+ * === Creating a Certificate
714
+ *
715
+ * This example creates a self-signed certificate using an RSA key and a SHA1
716
+ * signature.
717
+ *
718
+ * name = OpenSSL::X509::Name.parse 'CN=nobody/DC=example'
719
+ *
720
+ * cert = OpenSSL::X509::Certificate.new
721
+ * cert.version = 2
722
+ * cert.serial = 0
723
+ * cert.not_before = Time.now
724
+ * cert.not_after = Time.now + 3600
725
+ *
726
+ * cert.public_key = key.public_key
727
+ * cert.subject = name
728
+ *
729
+ * === Certificate Extensions
730
+ *
731
+ * You can add extensions to the certificate with
732
+ * OpenSSL::SSL::ExtensionFactory to indicate the purpose of the certificate.
733
+ *
734
+ * extension_factory = OpenSSL::X509::ExtensionFactory.new nil, cert
735
+ *
736
+ * cert.add_extension \
737
+ * extension_factory.create_extension('basicConstraints', 'CA:FALSE', true)
738
+ *
739
+ * cert.add_extension \
740
+ * extension_factory.create_extension(
741
+ * 'keyUsage', 'keyEncipherment,dataEncipherment,digitalSignature')
742
+ *
743
+ * cert.add_extension \
744
+ * extension_factory.create_extension('subjectKeyIdentifier', 'hash')
745
+ *
746
+ * The list of supported extensions (and in some cases their possible values)
747
+ * can be derived from the "objects.h" file in the OpenSSL source code.
748
+ *
749
+ * === Signing a Certificate
750
+ *
751
+ * To sign a certificate set the issuer and use OpenSSL::X509::Certificate#sign
752
+ * with a digest algorithm. This creates a self-signed cert because we're using
753
+ * the same name and key to sign the certificate as was used to create the
754
+ * certificate.
755
+ *
756
+ * cert.issuer = name
757
+ * cert.sign key, OpenSSL::Digest::SHA1.new
758
+ *
759
+ * open 'certificate.pem', 'w' do |io| io.write cert.to_pem end
760
+ *
761
+ * === Loading a Certificate
762
+ *
763
+ * Like a key, a cert can also be loaded from a file.
764
+ *
765
+ * cert2 = OpenSSL::X509::Certificate.new File.read 'certificate.pem'
766
+ *
767
+ * === Verifying a Certificate
768
+ *
769
+ * Certificate#verify will return true when a certificate was signed with the
770
+ * given public key.
771
+ *
772
+ * raise 'certificate can not be verified' unless cert2.verify key
773
+ *
774
+ * == Certificate Authority
775
+ *
776
+ * A certificate authority (CA) is a trusted third party that allows you to
777
+ * verify the ownership of unknown certificates. The CA issues key signatures
778
+ * that indicate it trusts the user of that key. A user encountering the key
779
+ * can verify the signature by using the CA's public key.
780
+ *
781
+ * === CA Key
782
+ *
783
+ * CA keys are valuable, so we encrypt and save it to disk and make sure it is
784
+ * not readable by other users.
785
+ *
786
+ * ca_key = OpenSSL::PKey::RSA.new 2048
787
+ *
788
+ * cipher = OpenSSL::Cipher::Cipher.new 'AES-128-CBC'
789
+ *
790
+ * open 'ca_key.pem', 'w', 0400 do |io|
791
+ * io.write key.export(cipher, pass_phrase)
792
+ * end
793
+ *
794
+ * === CA Certificate
795
+ *
796
+ * A CA certificate is created the same way we created a certificate above, but
797
+ * with different extensions.
798
+ *
799
+ * ca_name = OpenSSL::X509::Name.parse 'CN=ca/DC=example'
800
+ *
801
+ * ca_cert = OpenSSL::X509::Certificate.new
802
+ * ca_cert.serial = 0
803
+ * ca_cert.version = 2
804
+ * ca_cert.not_before = Time.now
805
+ * ca_cert.not_after = Time.now + 86400
806
+ *
807
+ * ca_cert.public_key = ca_key.public_key
808
+ * ca_cert.subject = ca_name
809
+ * ca_cert.issuer = ca_name
810
+ *
811
+ * extension_factory = OpenSSL::X509::ExtensionFactory.new
812
+ * extension_factory.subject_certificate = ca_cert
813
+ * extension_factory.issuer_certificate = ca_cert
814
+ *
815
+ * ca_cert.add_extension \
816
+ * extension_factory.create_extension('subjectKeyIdentifier', 'hash')
817
+ *
818
+ * This extension indicates the CA's key may be used as a CA.
819
+ *
820
+ * ca_cert.add_extension \
821
+ * extension_factory.create_extension('basicConstraints', 'CA:TRUE', true)
822
+ *
823
+ * This extension indicates the CA's key may be used to verify signatures on
824
+ * both certificates and certificate revocations.
825
+ *
826
+ * ca_cert.add_extension \
827
+ * extension_factory.create_extension(
828
+ * 'keyUsage', 'cRLSign,keyCertSign', true)
829
+ *
830
+ * Root CA certificates are self-signed.
831
+ *
832
+ * ca_cert.sign ca_key, OpenSSL::Digest::SHA1.new
833
+ *
834
+ * The CA certificate is saved to disk so it may be distributed to all the
835
+ * users of the keys this CA will sign.
836
+ *
837
+ * open 'ca_cert.pem', 'w' do |io|
838
+ * io.write ca_cert.to_pem
839
+ * end
840
+ *
841
+ * === Certificate Signing Request
842
+ *
843
+ * The CA signs keys through a Certificate Signing Request (CSR). The CSR
844
+ * contains the information necessary to identify the key.
845
+ *
846
+ * csr = OpenSSL::X509::Request.new
847
+ * csr.version = 0
848
+ * csr.subject = name
849
+ * csr.public_key = key.public_key
850
+ * csr.sign key, OpenSSL::Digest::SHA1.new
851
+ *
852
+ * A CSR is saved to disk and sent to the CA for signing.
853
+ *
854
+ * open 'csr.pem', 'w' do |io|
855
+ * io.write csr.to_pem
856
+ * end
857
+ *
858
+ * === Creating a Certificate from a CSR
859
+ *
860
+ * Upon receiving a CSR the CA will verify it before signing it. A minimal
861
+ * verification would be to check the CSR's signature.
862
+ *
863
+ * csr = OpenSSL::X509::Request.new File.read 'csr.pem'
864
+ *
865
+ * raise 'CSR can not be verified' unless csr.verify csr.public_key
866
+ *
867
+ * After verification a certificate is created, marked for various usages,
868
+ * signed with the CA key and returned to the requester.
869
+ *
870
+ * csr_cert = OpenSSL::X509::Certificate.new
871
+ * csr_cert.serial = 0
872
+ * csr_cert.version = 2
873
+ * csr_cert.not_before = Time.now
874
+ * csr_cert.not_after = Time.now + 600
875
+ *
876
+ * csr_cert.subject = csr.subject
877
+ * csr_cert.public_key = csr.public_key
878
+ * csr_cert.issuer = ca_cert.subject
879
+ *
880
+ * extension_factory = OpenSSL::X509::ExtensionFactory.new
881
+ * extension_factory.subject_certificate = csr_cert
882
+ * extension_factory.issuer_certificate = ca_cert
883
+ *
884
+ * csr_cert.add_extension \
885
+ * extension_factory.create_extension('basicConstraints', 'CA:FALSE')
886
+ *
887
+ * csr_cert.add_extension \
888
+ * extension_factory.create_extension(
889
+ * 'keyUsage', 'keyEncipherment,dataEncipherment,digitalSignature')
890
+ *
891
+ * csr_cert.add_extension \
892
+ * extension_factory.create_extension('subjectKeyIdentifier', 'hash')
893
+ *
894
+ * csr_cert.sign ca_key, OpenSSL::Digest::SHA1.new
895
+ *
896
+ * open 'csr_cert.pem', 'w' do |io|
897
+ * io.write csr_cert.to_pem
898
+ * end
899
+ *
900
+ * == SSL and TLS Connections
901
+ *
902
+ * Using our created key and certificate we can create an SSL or TLS connection.
903
+ * An SSLContext is used to set up an SSL session.
904
+ *
905
+ * context = OpenSSL::SSL::SSLContext.new
906
+ *
907
+ * === SSL Server
908
+ *
909
+ * An SSL server requires the certificate and private key to communicate
910
+ * securely with its clients:
911
+ *
912
+ * context.cert = cert
913
+ * context.key = key
914
+ *
915
+ * Then create an SSLServer with a TCP server socket and the context. Use the
916
+ * SSLServer like an ordinary TCP server.
917
+ *
918
+ * require 'socket'
919
+ *
920
+ * tcp_server = TCPServer.new 5000
921
+ * ssl_server = OpenSSL::SSL::SSLServer.new tcp_server, context
922
+ *
923
+ * loop do
924
+ * ssl_connection = ssl_server.accept
925
+ *
926
+ * data = connection.gets
927
+ *
928
+ * response = "I got #{data.dump}"
929
+ * puts response
930
+ *
931
+ * connection.puts "I got #{data.dump}"
932
+ * connection.close
933
+ * end
934
+ *
935
+ * === SSL client
936
+ *
937
+ * An SSL client is created with a TCP socket and the context.
938
+ * SSLSocket#connect must be called to initiate the SSL handshake and start
939
+ * encryption. A key and certificate are not required for the client socket.
940
+ *
941
+ * require 'socket'
942
+ *
943
+ * tcp_client = TCPSocket.new 'localhost', 5000
944
+ * ssl_client = OpenSSL::SSL::SSLSocket.new client_socket, context
945
+ * ssl_client.connect
946
+ *
947
+ * ssl_client.puts "hello server!"
948
+ * puts ssl_client.gets
949
+ *
950
+ * === Peer Verification
951
+ *
952
+ * An unverified SSL connection does not provide much security. For enhanced
953
+ * security the client or server can verify the certificate of its peer.
954
+ *
955
+ * The client can be modified to verify the server's certificate against the
956
+ * certificate authority's certificate:
957
+ *
958
+ * context.ca_file = 'ca_cert.pem'
959
+ * context.verify_mode = OpenSSL::SSL::VERIFY_PEER
960
+ *
961
+ * require 'socket'
962
+ *
963
+ * tcp_client = TCPSocket.new 'localhost', 5000
964
+ * ssl_client = OpenSSL::SSL::SSLSocket.new client_socket, context
965
+ * ssl_client.connect
966
+ *
967
+ * ssl_client.puts "hello server!"
968
+ * puts ssl_client.gets
969
+ *
970
+ * If the server certificate is invalid or <tt>context.ca_file</tt> is not set
971
+ * when verifying peers an OpenSSL::SSL::SSLError will be raised.
972
+ *
443
973
  */
444
974
  void
445
975
  Init_openssl()
@@ -482,12 +1012,31 @@ Init_openssl()
482
1012
  rb_global_variable(&mOSSL);
483
1013
 
484
1014
  /*
485
- * Constants
1015
+ * OpenSSL ruby extension version
486
1016
  */
487
1017
  rb_define_const(mOSSL, "VERSION", rb_str_new2(OSSL_VERSION));
1018
+
1019
+ /*
1020
+ * Version of OpenSSL the ruby OpenSSL extension was built with
1021
+ */
488
1022
  rb_define_const(mOSSL, "OPENSSL_VERSION", rb_str_new2(OPENSSL_VERSION_TEXT));
1023
+
1024
+ /*
1025
+ * Version number of OpenSSL the ruby OpenSSL extension was built with
1026
+ * (base 16)
1027
+ */
489
1028
  rb_define_const(mOSSL, "OPENSSL_VERSION_NUMBER", INT2NUM(OPENSSL_VERSION_NUMBER));
490
1029
 
1030
+ /*
1031
+ * Boolean indicating whether OpenSSL is FIPS-enabled or not
1032
+ */
1033
+ #ifdef HAVE_OPENSSL_FIPS
1034
+ rb_define_const(mOSSL, "OPENSSL_FIPS", Qtrue);
1035
+ #else
1036
+ rb_define_const(mOSSL, "OPENSSL_FIPS", Qfalse);
1037
+ #endif
1038
+ rb_define_module_function(mOSSL, "fips_mode=", ossl_fips_mode_set, 1);
1039
+
491
1040
  /*
492
1041
  * Generic error,
493
1042
  * common for all classes under OpenSSL module
@@ -498,7 +1047,7 @@ Init_openssl()
498
1047
  /*
499
1048
  * Verify callback Proc index for ext-data
500
1049
  */
501
- if ((ossl_verify_cb_idx = X509_STORE_CTX_get_ex_new_index(0, "ossl_verify_cb_idx", 0, 0, 0)) < 0)
1050
+ if ((ossl_verify_cb_idx = X509_STORE_CTX_get_ex_new_index(0, (void *)"ossl_verify_cb_idx", 0, 0, 0)) < 0)
502
1051
  ossl_raise(eOSSLError, "X509_STORE_CTX_get_ex_new_index");
503
1052
 
504
1053
  /*
@@ -544,7 +1093,7 @@ Init_openssl()
544
1093
  * Check if all symbols are OK with 'make LDSHARED=gcc all'
545
1094
  */
546
1095
  int
547
- main(int argc, char *argv[], char *env[])
1096
+ main(int argc, char *argv[])
548
1097
  {
549
1098
  return 0;
550
1099
  }