rubysl-openssl 1.0.2 → 2.0.0

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