[rubygem-openssl_cms] Add support for ruby 2.2.

František Dvořák valtri at fedoraproject.org
Wed Jan 28 21:54:42 UTC 2015


commit 4655d8fd605649f9d3d9b1976558e1f386f3e7a9
Author: František Dvořák <valtri at civ.zcu.cz>
Date:   Wed Jan 28 22:30:01 2015 +0100

    Add support for ruby 2.2.

 openssl_cms-ruby2.1.5.diff |  877 +++++++++++++
 openssl_cms-ruby2.2.0.diff | 3135 ++++++++++++++++++++++++++++++++++++++++++++
 rubygem-openssl_cms.spec   |   39 +-
 3 files changed, 4039 insertions(+), 12 deletions(-)
---
diff --git a/openssl_cms-ruby2.1.5.diff b/openssl_cms-ruby2.1.5.diff
new file mode 100644
index 0000000..4b68240
--- /dev/null
+++ b/openssl_cms-ruby2.1.5.diff
@@ -0,0 +1,877 @@
+commit b6bdfb4c3c61c77251b89f096b80234fab728731
+Author: František Dvořák <valtri at civ.zcu.cz>
+Date:   Wed Jan 28 18:16:16 2015 +0100
+
+    Sync with ruby 2.1.5 (patch 285, release date 2015-01-22).
+
+diff --git a/ext/openssl_cms/ossl.c b/ext/openssl_cms/ossl.c
+index 64a93a4..34378e4 100644
+--- a/ext/openssl_cms/ossl.c
++++ b/ext/openssl_cms/ossl.c
+@@ -311,10 +311,11 @@ ossl_make_error(VALUE exc, const char *fmt, va_list args)
+ 	else
+ 	    msg = ERR_reason_error_string(e);
+ 	if (NIL_P(str)) {
+-	    str = rb_str_new_cstr(msg);
++	    if (msg) str = rb_str_new_cstr(msg);
+ 	}
+ 	else {
+-	    rb_str_cat2(rb_str_cat2(str, ": "), msg);
++	    if (RSTRING_LEN(str)) rb_str_cat2(str, ": ");
++	    rb_str_cat2(str, msg ? msg : "(null)");
+ 	}
+     }
+     if (dOSSL == Qtrue){ /* show all errors on the stack */
+@@ -1082,6 +1083,11 @@ Init_openssl_cms()
+     rb_define_const(mOSSL, "OPENSSL_VERSION", rb_str_new2(OPENSSL_VERSION_TEXT));
+ 
+     /*
++     * Version of OpenSSL the ruby OpenSSL extension is running with
++     */
++    rb_define_const(mOSSL, "OPENSSL_LIBRARY_VERSION", rb_str_new2(SSLeay_version(SSLEAY_VERSION)));
++
++    /*
+      * Version number of OpenSSL the ruby OpenSSL extension was built with
+      * (base 16)
+      */
+diff --git a/ext/openssl_cms/ossl_asn1.c b/ext/openssl_cms/ossl_asn1.c
+index c2344af..efdfbfc 100644
+--- a/ext/openssl_cms/ossl_asn1.c
++++ b/ext/openssl_cms/ossl_asn1.c
+@@ -1150,7 +1150,7 @@ ossl_asn1_initialize(int argc, VALUE *argv, VALUE self)
+ 	}
+ 	if(!SYMBOL_P(tag_class))
+ 	    ossl_raise(eASN1Error, "invalid tag class");
+-	if(SYM2ID(tagging) == sIMPLICIT && NUM2INT(tag) > 31)
++	if(!NIL_P(tagging) && SYM2ID(tagging) == sIMPLICIT && NUM2INT(tag) > 31)
+ 	    ossl_raise(eASN1Error, "tag number for Universal too large");
+     }
+     else{
+diff --git a/ext/openssl_cms/ossl_cipher.c b/ext/openssl_cms/ossl_cipher.c
+index df6fd10..0fa740e 100644
+--- a/ext/openssl_cms/ossl_cipher.c
++++ b/ext/openssl_cms/ossl_cipher.c
+@@ -329,6 +329,33 @@ ossl_cipher_pkcs5_keyivgen(int argc, VALUE *argv, VALUE self)
+     return Qnil;
+ }
+ 
++static int
++ossl_cipher_update_long(EVP_CIPHER_CTX *ctx, unsigned char *out, long *out_len_ptr,
++			const unsigned char *in, long in_len)
++{
++    int out_part_len;
++    long out_len = 0;
++#define UPDATE_LENGTH_LIMIT INT_MAX
++
++#if SIZEOF_LONG > UPDATE_LENGTH_LIMIT
++    if (in_len > UPDATE_LENGTH_LIMIT) {
++	const int in_part_len = (UPDATE_LENGTH_LIMIT / 2 + 1) & ~1;
++	do {
++	    if (!EVP_CipherUpdate(ctx, out ? (out + out_len) : 0,
++				  &out_part_len, in, in_part_len))
++		return 0;
++	    out_len += out_part_len;
++	    in += in_part_len;
++	} while ((in_len -= in_part_len) > UPDATE_LENGTH_LIMIT);
++    }
++#endif
++    if (!EVP_CipherUpdate(ctx, out ? (out + out_len) : 0,
++			  &out_part_len, in, (int)in_len))
++	return 0;
++    if (out_len_ptr) *out_len_ptr = out_len += out_part_len;
++    return 1;
++}
++
+ /*
+  *  call-seq:
+  *     cipher.update(data [, buffer]) -> string or buffer
+@@ -347,17 +374,21 @@ ossl_cipher_update(int argc, VALUE *argv, VALUE self)
+ {
+     EVP_CIPHER_CTX *ctx;
+     unsigned char *in;
+-    int in_len, out_len;
++    long in_len, out_len;
+     VALUE data, str;
+ 
+     rb_scan_args(argc, argv, "11", &data, &str);
+ 
+     StringValue(data);
+     in = (unsigned char *)RSTRING_PTR(data);
+-    if ((in_len = RSTRING_LENINT(data)) == 0)
++    if ((in_len = RSTRING_LEN(data)) == 0)
+         ossl_raise(rb_eArgError, "data must not be empty");
+     GetCipher(self, ctx);
+     out_len = in_len+EVP_CIPHER_CTX_block_size(ctx);
++    if (out_len <= 0) {
++	ossl_raise(rb_eRangeError,
++		   "data too big to make output buffer: %ld bytes", in_len);
++    }
+ 
+     if (NIL_P(str)) {
+         str = rb_str_new(0, out_len);
+@@ -366,7 +397,7 @@ ossl_cipher_update(int argc, VALUE *argv, VALUE self)
+         rb_str_resize(str, out_len);
+     }
+ 
+-    if (!EVP_CipherUpdate(ctx, (unsigned char *)RSTRING_PTR(str), &out_len, in, in_len))
++    if (!ossl_cipher_update_long(ctx, (unsigned char *)RSTRING_PTR(str), &out_len, in, in_len))
+ 	ossl_raise(eCipherError, NULL);
+     assert(out_len < RSTRING_LEN(str));
+     rb_str_set_len(str, out_len);
+@@ -506,17 +537,16 @@ ossl_cipher_set_auth_data(VALUE self, VALUE data)
+ {
+     EVP_CIPHER_CTX *ctx;
+     unsigned char *in;
+-    int in_len;
+-    int out_len;
++    long in_len, out_len;
+ 
+     StringValue(data);
+ 
+     in = (unsigned char *) RSTRING_PTR(data);
+-    in_len = RSTRING_LENINT(data);
++    in_len = RSTRING_LEN(data);
+ 
+     GetCipher(self, ctx);
+ 
+-    if (!EVP_CipherUpdate(ctx, NULL, &out_len, in, in_len))
++    if (!ossl_cipher_update_long(ctx, NULL, &out_len, in, in_len))
+         ossl_raise(eCipherError, "couldn't set additional authenticated data");
+ 
+     return data;
+diff --git a/ext/openssl_cms/ossl_pkey.c b/ext/openssl_cms/ossl_pkey.c
+index 0004d9d..878b221 100644
+--- a/ext/openssl_cms/ossl_pkey.c
++++ b/ext/openssl_cms/ossl_pkey.c
+@@ -318,13 +318,16 @@ ossl_pkey_verify(VALUE self, VALUE digest, VALUE sig, VALUE data)
+ {
+     EVP_PKEY *pkey;
+     EVP_MD_CTX ctx;
++    int result;
+ 
+     GetPKey(self, pkey);
+-    EVP_VerifyInit(&ctx, GetDigestPtr(digest));
+     StringValue(sig);
+     StringValue(data);
++    EVP_VerifyInit(&ctx, GetDigestPtr(digest));
+     EVP_VerifyUpdate(&ctx, RSTRING_PTR(data), RSTRING_LEN(data));
+-    switch (EVP_VerifyFinal(&ctx, (unsigned char *)RSTRING_PTR(sig), RSTRING_LENINT(sig), pkey)) {
++    result = EVP_VerifyFinal(&ctx, (unsigned char *)RSTRING_PTR(sig), RSTRING_LENINT(sig), pkey);
++    EVP_MD_CTX_cleanup(&ctx);
++    switch (result) {
+     case 0:
+ 	return Qfalse;
+     case 1:
+diff --git a/ext/openssl_cms/ossl_pkey_dh.c b/ext/openssl_cms/ossl_pkey_dh.c
+index a6ae006..011b6f0 100644
+--- a/ext/openssl_cms/ossl_pkey_dh.c
++++ b/ext/openssl_cms/ossl_pkey_dh.c
+@@ -621,7 +621,7 @@ Init_ossl_dh()
+      *
+      * === Example of a key exchange
+      *  dh1 = OpenSSL::PKey::DH.new(2048)
+-     *  params = dh1.public_key.to_der #you may send this publicly to the participating party
++     *  der = dh1.public_key.to_der #you may send this publicly to the participating party
+      *  dh2 = OpenSSL::PKey::DH.new(der)
+      *  dh2.generate_key! #generate the per-session key pair
+      *  symm_key1 = dh1.compute_key(dh2.pub_key)
+@@ -664,4 +664,3 @@ Init_ossl_dh()
+ {
+ }
+ #endif /* NO_DH */
+-
+diff --git a/lib/openssl_cms/bn.rb b/lib/openssl_cms/bn.rb
+index b2fca16..0e19c20 100644
+--- a/lib/openssl_cms/bn.rb
++++ b/lib/openssl_cms/bn.rb
+@@ -3,16 +3,16 @@
+ # $RCSfile$
+ #
+ # = Ruby-space definitions that completes C-space funcs for BN
+-# 
++#
+ # = Info
+ # 'OpenSSL for Ruby 2' project
+ # Copyright (C) 2002  Michal Rokos <m.rokos at sh.cvut.cz>
+ # All rights reserved.
+-# 
++#
+ # = Licence
+ # This program is licenced under the same licence as Ruby.
+ # (See the file 'LICENCE'.)
+-# 
++#
+ # = Version
+ # $Id$
+ #
+@@ -28,8 +28,11 @@ end # OpenSSL
+ # Add double dispatch to Integer
+ #
+ class Integer
++  # Casts an Integer as an OpenSSL::BN
++  #
++  # See `man bn` for more info.
+   def to_bn
+-    OpenSSL::BN::new(self.to_s(16), 16)
++    OpenSSL::BN::new(self)
+   end
+ end # Integer
+ 
+diff --git a/lib/openssl_cms/buffering.rb b/lib/openssl_cms/buffering.rb
+index 51bc968..1223c5d 100644
+--- a/lib/openssl_cms/buffering.rb
++++ b/lib/openssl_cms/buffering.rb
+@@ -1,23 +1,27 @@
+-=begin
+-= $RCSfile$ -- Buffering mix-in module.
+-
+-= Info
+-  'OpenSSL for Ruby 2' project
+-  Copyright (C) 2001 GOTOU YUUZOU <gotoyuzo at notwork.org>
+-  All rights reserved.
+-
+-= Licence
+-  This program is licenced under the same licence as Ruby.
+-  (See the file 'LICENCE'.)
+-
+-= Version
+-  $Id$
+-=end
++# coding: binary
++#--
++#= $RCSfile$ -- Buffering mix-in module.
++#
++#= Info
++#  'OpenSSL for Ruby 2' project
++#  Copyright (C) 2001 GOTOU YUUZOU <gotoyuzo at notwork.org>
++#  All rights reserved.
++#
++#= Licence
++#  This program is licenced under the same licence as Ruby.
++#  (See the file 'LICENCE'.)
++#
++#= Version
++#  $Id$
++#++
+ 
+ ##
+ # OpenSSL IO buffering mix-in module.
+ #
+ # This module allows an OpenSSL::SSL::SSLSocket to behave like an IO.
++#
++# You typically won't use this module directly, you can see it implemented in
++# OpenSSL::SSL::SSLSocket.
+ 
+ module OpenSSL::Buffering
+   include Enumerable
+@@ -34,7 +38,11 @@ module OpenSSL::Buffering
+ 
+   BLOCK_SIZE = 1024*16
+ 
+-  def initialize(*args)
++  ##
++  # Creates an instance of OpenSSL's buffering IO module.
++
++  def initialize(*)
++    super
+     @eof = false
+     @rbuffer = ""
+     @sync = @io.sync
+@@ -161,7 +169,7 @@ module OpenSSL::Buffering
+   # when the peer requests a new TLS/SSL handshake.  See openssl the FAQ for
+   # more details.  http://www.openssl.org/support/faq.html
+ 
+-  def read_nonblock(maxlen, buf=nil)
++  def read_nonblock(maxlen, buf=nil, exception: true)
+     if maxlen == 0
+       if buf
+         buf.clear
+@@ -171,7 +179,7 @@ module OpenSSL::Buffering
+       end
+     end
+     if @rbuffer.empty?
+-      return sysread_nonblock(maxlen, buf)
++      return sysread_nonblock(maxlen, buf, exception: exception)
+     end
+     ret = consume_rbuff(maxlen)
+     if buf
+@@ -370,9 +378,9 @@ module OpenSSL::Buffering
+   # is when the peer requests a new TLS/SSL handshake.  See the openssl FAQ
+   # for more details.  http://www.openssl.org/support/faq.html
+ 
+-  def write_nonblock(s)
++  def write_nonblock(s, exception: true)
+     flush
+-    syswrite_nonblock(s)
++    syswrite_nonblock(s, exception: exception)
+   end
+ 
+   ##
+diff --git a/lib/openssl_cms/cipher.rb b/lib/openssl_cms/cipher.rb
+index eb146fb..b3340ff 100644
+--- a/lib/openssl_cms/cipher.rb
++++ b/lib/openssl_cms/cipher.rb
+@@ -3,16 +3,16 @@
+ # $RCSfile$
+ #
+ # = Ruby-space predefined Cipher subclasses
+-# 
++#
+ # = Info
+ # 'OpenSSL for Ruby 2' project
+ # Copyright (C) 2002  Michal Rokos <m.rokos at sh.cvut.cz>
+ # All rights reserved.
+-# 
++#
+ # = Licence
+ # This program is licenced under the same licence as Ruby.
+ # (See the file 'LICENCE'.)
+-# 
++#
+ # = Version
+ # $Id$
+ #
+diff --git a/lib/openssl_cms/config.rb b/lib/openssl_cms/config.rb
+index 24a54c9..5716d59 100644
+--- a/lib/openssl_cms/config.rb
++++ b/lib/openssl_cms/config.rb
+@@ -13,20 +13,41 @@
+ require 'stringio'
+ 
+ module OpenSSL
++  ##
++  # = OpenSSL::Config
++  #
++  # Configuration for the openssl library.
++  #
++  # Many system's installation of openssl library will depend on your system
++  # configuration. See the value of OpenSSL::Config::DEFAULT_CONFIG_FILE for
++  # the location of the file for your host.
++  #
++  # See also http://www.openssl.org/docs/apps/config.html
+   class Config
+     include Enumerable
+ 
+     class << self
+-      def parse(str)
++
++      ##
++      # Parses a given +string+ as a blob that contains configuration for openssl.
++      #
++      # If the source of the IO is a file, then consider using #parse_config.
++      def parse(string)
+         c = new()
+-        parse_config(StringIO.new(str)).each do |section, hash|
++        parse_config(StringIO.new(string)).each do |section, hash|
+           c[section] = hash
+         end
+         c
+       end
+ 
++      ##
++      # load is an alias to ::new
+       alias load new
+ 
++      ##
++      # Parses the configuration data read from +io+, see also #parse.
++      #
++      # Raises a ConfigError on invalid configuration data.
+       def parse_config(io)
+         begin
+           parse_config_lines(io)
+@@ -209,6 +230,18 @@ module OpenSSL
+       end
+     end
+ 
++    ##
++    # Creates an instance of OpenSSL's configuration class.
++    #
++    # This can be used in contexts like OpenSSL::X509::ExtensionFactory.config=
++    #
++    # If the optional +filename+ parameter is provided, then it is read in and
++    # parsed via #parse_config.
++    #
++    # This can raise IO exceptions based on the access, or availability of the
++    # file. A ConfigError exception may be raised depending on the validity of
++    # the data being configured.
++    #
+     def initialize(filename = nil)
+       @data = {}
+       if filename
+@@ -220,6 +253,23 @@ module OpenSSL
+       end
+     end
+ 
++    ##
++    # Gets the value of +key+ from the given +section+
++    #
++    # Given the following configurating file being loaded:
++    #
++    #   config = OpenSSL::Config.load('foo.cnf')
++    #     #=> #<OpenSSL::Config sections=["default"]>
++    #   puts config.to_s
++    #     #=> [ default ]
++    #     #   foo=bar
++    #
++    # You can get a specific value from the config if you know the +section+
++    # and +key+ like so:
++    #
++    #   config.get_value('default','foo')
++    #     #=> "bar"
++    #
+     def get_value(section, key)
+       if section.nil?
+         raise TypeError.new('nil not allowed')
+@@ -228,7 +278,12 @@ module OpenSSL
+       get_key_string(section, key)
+     end
+ 
+-    def value(arg1, arg2 = nil)
++    ##
++    #
++    # *Deprecated*
++    #
++    # Use #get_value instead
++    def value(arg1, arg2 = nil) # :nodoc:
+       warn('Config#value is deprecated; use Config#get_value')
+       if arg2.nil?
+         section, key = 'default', arg1
+@@ -240,20 +295,84 @@ module OpenSSL
+       get_key_string(section, key)
+     end
+ 
++    ##
++    # Set the target +key+ with a given +value+ under a specific +section+.
++    #
++    # Given the following configurating file being loaded:
++    #
++    #   config = OpenSSL::Config.load('foo.cnf')
++    #     #=> #<OpenSSL::Config sections=["default"]>
++    #   puts config.to_s
++    #     #=> [ default ]
++    #     #   foo=bar
++    #
++    # You can set the value of +foo+ under the +default+ section to a new
++    # value:
++    #
++    #   config.add_value('default', 'foo', 'buzz')
++    #     #=> "buzz"
++    #   puts config.to_s
++    #     #=> [ default ]
++    #     #   foo=buzz
++    #
+     def add_value(section, key, value)
+       check_modify
+       (@data[section] ||= {})[key] = value
+     end
+ 
++    ##
++    # Get a specific +section+ from the current configuration
++    #
++    # Given the following configurating file being loaded:
++    #
++    #   config = OpenSSL::Config.load('foo.cnf')
++    #     #=> #<OpenSSL::Config sections=["default"]>
++    #   puts config.to_s
++    #     #=> [ default ]
++    #     #   foo=bar
++    #
++    # You can get a hash of the specific section like so:
++    #
++    #   config['default']
++    #     #=> {"foo"=>"bar"}
++    #
+     def [](section)
+       @data[section] || {}
+     end
+ 
+-    def section(name)
++    ##
++    # Deprecated
++    #
++    # Use #[] instead
++    def section(name) # :nodoc:
+       warn('Config#section is deprecated; use Config#[]')
+       @data[name] || {}
+     end
+ 
++    ##
++    # Sets a specific +section+ name with a Hash +pairs+
++    #
++    # Given the following configuration being created:
++    #
++    #   config = OpenSSL::Config.new
++    #     #=> #<OpenSSL::Config sections=[]>
++    #   config['default'] = {"foo"=>"bar","baz"=>"buz"}
++    #     #=> {"foo"=>"bar", "baz"=>"buz"}
++    #   puts config.to_s
++    #     #=> [ default ]
++    #     #   foo=bar
++    #     #   baz=buz
++    #
++    # It's important to note that this will essentially merge any of the keys
++    # in +pairs+ with the existing +section+. For example:
++    #
++    #   config['default']
++    #     #=> {"foo"=>"bar", "baz"=>"buz"}
++    #   config['default'] = {"foo" => "changed"}
++    #     #=> {"foo"=>"changed"}
++    #   config['default']
++    #     #=> {"foo"=>"changed", "baz"=>"buz"}
++    #
+     def []=(section, pairs)
+       check_modify
+       @data[section] ||= {}
+@@ -262,10 +381,38 @@ module OpenSSL
+       end
+     end
+ 
++    ##
++    # Get the names of all sections in the current configuration
+     def sections
+       @data.keys
+     end
+ 
++    ##
++    # Get the parsable form of the current configuration
++    #
++    # Given the following configuration being created:
++    #
++    #   config = OpenSSL::Config.new
++    #     #=> #<OpenSSL::Config sections=[]>
++    #   config['default'] = {"foo"=>"bar","baz"=>"buz"}
++    #     #=> {"foo"=>"bar", "baz"=>"buz"}
++    #   puts config.to_s
++    #     #=> [ default ]
++    #     #   foo=bar
++    #     #   baz=buz
++    #
++    # You can parse get the serialized configuration using #to_s and then parse
++    # it later:
++    #
++    #   serialized_config = config.to_s
++    #   # much later...
++    #   new_config = OpenSSL::Config.parse(serialized_config)
++    #     #=> #<OpenSSL::Config sections=["default"]>
++    #   puts new_config
++    #     #=> [ default ]
++    #         foo=bar
++    #         baz=buz
++    #
+     def to_s
+       ary = []
+       @data.keys.sort.each do |section|
+@@ -278,6 +425,15 @@ module OpenSSL
+       ary.join
+     end
+ 
++    ##
++    # For a block.
++    #
++    # Receive the section and its pairs for the current configuration.
++    #
++    #   config.each do |section, key, value|
++    #     # ...
++    #   end
++    #
+     def each
+       @data.each do |section, hash|
+         hash.each do |key, value|
+@@ -286,13 +442,16 @@ module OpenSSL
+       end
+     end
+ 
++    ##
++    # String representation of this configuration object, including the class
++    # name and its sections.
+     def inspect
+       "#<#{self.class.name} sections=#{sections.inspect}>"
+     end
+ 
+   protected
+ 
+-    def data
++    def data # :nodoc:
+       @data
+     end
+ 
+diff --git a/lib/openssl_cms/digest.rb b/lib/openssl_cms/digest.rb
+index b470071..a7b641f 100644
+--- a/lib/openssl_cms/digest.rb
++++ b/lib/openssl_cms/digest.rb
+@@ -3,16 +3,16 @@
+ # $RCSfile$
+ #
+ # = Ruby-space predefined Digest subclasses
+-# 
++#
+ # = Info
+ # 'OpenSSL for Ruby 2' project
+ # Copyright (C) 2002  Michal Rokos <m.rokos at sh.cvut.cz>
+ # All rights reserved.
+-# 
++#
+ # = Licence
+ # This program is licenced under the same licence as Ruby.
+ # (See the file 'LICENCE'.)
+-# 
++#
+ # = Version
+ # $Id$
+ #
+@@ -31,42 +31,58 @@ module OpenSSL
+     #
+     # === Examples
+     #
+-    #   OpenSSL::Digest.digest("SHA256, "abc")
++    #   OpenSSL::Digest.digest("SHA256", "abc")
+     #
+     # which is equivalent to:
+     #
+     #   OpenSSL::Digest::SHA256.digest("abc")
+ 
+     def self.digest(name, data)
+-        super(data, name)
++      super(data, name)
+     end
+ 
+     alg.each{|name|
+-      klass = Class.new(Digest){
+-        define_method(:initialize){|*data|
+-          if data.length > 1
+-            raise ArgumentError,
+-              "wrong number of arguments (#{data.length} for 1)"
+-          end
+-          super(name, data.first)
+-        }
++      klass = Class.new(self) {
++        define_method(:initialize, ->(data = nil) {super(name, data)})
+       }
+       singleton = (class << klass; self; end)
+       singleton.class_eval{
+-        define_method(:digest){|data| Digest.digest(name, data) }
+-        define_method(:hexdigest){|data| Digest.hexdigest(name, data) }
++        define_method(:digest){|data| new.digest(data) }
++        define_method(:hexdigest){|data| new.hexdigest(data) }
+       }
+       const_set(name, klass)
+     }
+ 
+-    # This class is only provided for backwards compatibility.  Use OpenSSL::Digest in the future.
+-    class Digest < Digest
++    # Deprecated.
++    #
++    # This class is only provided for backwards compatibility.
++    class Digest < Digest # :nodoc:
++      # Deprecated.
++      #
++      # See OpenSSL::Digest.new
+       def initialize(*args)
+-        # add warning
++        warn('Digest::Digest is deprecated; use Digest')
+         super(*args)
+       end
+     end
+ 
+   end # Digest
++
++  # Returns a Digest subclass by +name+.
++  #
++  #   require 'openssl'
++  #
++  #   OpenSSL::Digest("MD5")
++  #   # => OpenSSL::Digest::MD5
++  #
++  #   Digest("Foo")
++  #   # => NameError: wrong constant name Foo
++
++  def Digest(name)
++    OpenSSL::Digest.const_get(name)
++  end
++
++  module_function :Digest
++
+ end # OpenSSL
+ 
+diff --git a/lib/openssl_cms/ssl-internal.rb b/lib/openssl_cms/ssl-internal.rb
+index ff8a898..cb5887e 100644
+--- a/lib/openssl_cms/ssl-internal.rb
++++ b/lib/openssl_cms/ssl-internal.rb
+@@ -23,8 +23,49 @@ module OpenSSL
+       DEFAULT_PARAMS = {
+         :ssl_version => "SSLv23",
+         :verify_mode => OpenSSL::SSL::VERIFY_PEER,
+-        :ciphers => "ALL:!ADH:!EXPORT:!SSLv2:RC4+RSA:+HIGH:+MEDIUM:+LOW",
+-        :options => OpenSSL::SSL::OP_ALL,
++        :ciphers => %w{
++          ECDHE-ECDSA-AES128-GCM-SHA256
++          ECDHE-RSA-AES128-GCM-SHA256
++          ECDHE-ECDSA-AES256-GCM-SHA384
++          ECDHE-RSA-AES256-GCM-SHA384
++          DHE-RSA-AES128-GCM-SHA256
++          DHE-DSS-AES128-GCM-SHA256
++          DHE-RSA-AES256-GCM-SHA384
++          DHE-DSS-AES256-GCM-SHA384
++          ECDHE-ECDSA-AES128-SHA256
++          ECDHE-RSA-AES128-SHA256
++          ECDHE-ECDSA-AES128-SHA
++          ECDHE-RSA-AES128-SHA
++          ECDHE-ECDSA-AES256-SHA384
++          ECDHE-RSA-AES256-SHA384
++          ECDHE-ECDSA-AES256-SHA
++          ECDHE-RSA-AES256-SHA
++          DHE-RSA-AES128-SHA256
++          DHE-RSA-AES256-SHA256
++          DHE-RSA-AES128-SHA
++          DHE-RSA-AES256-SHA
++          DHE-DSS-AES128-SHA256
++          DHE-DSS-AES256-SHA256
++          DHE-DSS-AES128-SHA
++          DHE-DSS-AES256-SHA
++          AES128-GCM-SHA256
++          AES256-GCM-SHA384
++          AES128-SHA256
++          AES256-SHA256
++          AES128-SHA
++          AES256-SHA
++          ECDHE-ECDSA-RC4-SHA
++          ECDHE-RSA-RC4-SHA
++          RC4-SHA
++        }.join(":"),
++        :options => -> {
++          opts = OpenSSL::SSL::OP_ALL
++          opts &= ~OpenSSL::SSL::OP_DONT_INSERT_EMPTY_FRAGMENTS if defined?(OpenSSL::SSL::OP_DONT_INSERT_EMPTY_FRAGMENTS)
++          opts |= OpenSSL::SSL::OP_NO_COMPRESSION if defined?(OpenSSL::SSL::OP_NO_COMPRESSION)
++          opts |= OpenSSL::SSL::OP_NO_SSLv2 if defined?(OpenSSL::SSL::OP_NO_SSLv2)
++          opts |= OpenSSL::SSL::OP_NO_SSLv3 if defined?(OpenSSL::SSL::OP_NO_SSLv3)
++          opts
++        }.call
+       }
+ 
+       DEFAULT_CERT_STORE = OpenSSL::X509::Store.new
+@@ -33,6 +74,14 @@ module OpenSSL
+         DEFAULT_CERT_STORE.flags = OpenSSL::X509::V_FLAG_CRL_CHECK_ALL
+       end
+ 
++      ##
++      # Sets the parameters for this SSL context to the values in +params+.
++      # The keys in +params+ must be assignment methods on SSLContext.
++      #
++      # If the verify_mode is not VERIFY_NONE and ca_file, ca_path and
++      # cert_store are not set then the system default certificate store is
++      # used.
++
+       def set_params(params={})
+         params = DEFAULT_PARAMS.merge(params)
+         params.each{|name, value| self.__send__("#{name}=", value) }
+@@ -126,7 +175,7 @@ module OpenSSL
+ 
+       def post_connection_check(hostname)
+         unless OpenSSL::SSL.verify_certificate_identity(peer_cert, hostname)
+-          raise SSLError, "hostname does not match the server certificate"
++          raise SSLError, "hostname \"#{hostname}\" does not match the server certificate"
+         end
+         return true
+       end
+@@ -138,34 +187,49 @@ module OpenSSL
+       end
+     end
+ 
++    ##
++    # SSLServer represents a TCP/IP server socket with Secure Sockets Layer.
+     class SSLServer
+       include SocketForwarder
++      # When true then #accept works exactly the same as TCPServer#accept
+       attr_accessor :start_immediately
+ 
++      # Creates a new instance of SSLServer.
++      # * +srv+ is an instance of TCPServer.
++      # * +ctx+ is an instance of OpenSSL::SSL::SSLContext.
+       def initialize(svr, ctx)
+         @svr = svr
+         @ctx = ctx
+         unless ctx.session_id_context
+-          session_id = OpenSSL::Digest::MD5.hexdigest($0)
++          # see #6137 - session id may not exceed 32 bytes
++          prng = ::Random.new($0.hash)
++          session_id = prng.bytes(16).unpack('H*')[0]
+           @ctx.session_id_context = session_id
+         end
+         @start_immediately = true
+       end
+ 
++      # Returns the TCPServer passed to the SSLServer when initialized.
+       def to_io
+         @svr
+       end
+ 
++      # See TCPServer#listen for details.
+       def listen(backlog=5)
+         @svr.listen(backlog)
+       end
+ 
++      # See BasicSocket#shutdown for details.
+       def shutdown(how=Socket::SHUT_RDWR)
+         @svr.shutdown(how)
+       end
+ 
++      # Works similar to TCPServer#accept.
+       def accept
+-        sock = @svr.accept
++        # Socket#accept returns [socket, addrinfo].
++        # TCPServer#accept returns a socket.
++        # The following comma strips addrinfo.
++        sock, = @svr.accept
+         begin
+           ssl = OpenSSL::SSL::SSLSocket.new(sock, @ctx)
+           ssl.sync_close = true
+@@ -177,6 +241,7 @@ module OpenSSL
+         end
+       end
+ 
++      # See IO#close for details.
+       def close
+         @svr.close
+       end
+diff --git a/lib/openssl_cms/x509-internal.rb b/lib/openssl_cms/x509-internal.rb
+index 47e3a6f..31a4381 100644
+--- a/lib/openssl_cms/x509-internal.rb
++++ b/lib/openssl_cms/x509-internal.rb
+@@ -1,18 +1,22 @@
+-=begin
+-= $RCSfile$ -- Ruby-space definitions that completes C-space funcs for X509 and subclasses
+-
+-= Info
+-  'OpenSSL for Ruby 2' project
+-  Copyright (C) 2002  Michal Rokos <m.rokos at sh.cvut.cz>
+-  All rights reserved.
+-
+-= Licence
+-  This program is licenced under the same licence as Ruby.
+-  (See the file 'LICENCE'.)
+-
+-= Version
+-  $Id$
+-=end
++#--
++#
++# $RCSfile$
++#
++# = Ruby-space definitions that completes C-space funcs for X509 and subclasses
++#
++# = Info
++# 'OpenSSL for Ruby 2' project
++# Copyright (C) 2002  Michal Rokos <m.rokos at sh.cvut.cz>
++# All rights reserved.
++#
++# = Licence
++# This program is licenced under the same licence as Ruby.
++# (See the file 'LICENCE'.)
++#
++# = Version
++# $Id$
++#
++#++
+ 
+ module OpenSSL
+   module X509
diff --git a/openssl_cms-ruby2.2.0.diff b/openssl_cms-ruby2.2.0.diff
new file mode 100644
index 0000000..930673f
--- /dev/null
+++ b/openssl_cms-ruby2.2.0.diff
@@ -0,0 +1,3135 @@
+commit 668b7abd28461836941ce2be4fe7703053aeb42e
+Author: František Dvořák <valtri at civ.zcu.cz>
+Date:   Wed Jan 28 18:50:41 2015 +0100
+
+    Sync with ruby 2.2.0 (patch 37, release date 2015-01-26).
+
+diff --git a/ext/openssl_cms/ossl.c b/ext/openssl_cms/ossl.c
+index 34378e4..2e8f034 100644
+--- a/ext/openssl_cms/ossl.c
++++ b/ext/openssl_cms/ossl.c
+@@ -18,11 +18,12 @@ int
+ string2hex(const unsigned char *buf, int buf_len, char **hexbuf, int *hexbuf_len)
+ {
+     static const char hex[]="0123456789abcdef";
+-    int i, len = 2 * buf_len;
++    int i, len;
+ 
+-    if (buf_len < 0 || len < buf_len) { /* PARANOIA? */
++    if (buf_len < 0 || buf_len > INT_MAX / 2) { /* PARANOIA? */
+ 	return -1;
+     }
++    len = 2 * buf_len;
+     if (!hexbuf) { /* if no buf, return calculated len */
+ 	if (hexbuf_len) {
+ 	    *hexbuf_len = len;
+@@ -360,7 +361,7 @@ ossl_exc_new(VALUE exc, const char *fmt, ...)
+  * Any errors you see here are probably due to a bug in ruby's OpenSSL implementation.
+  */
+ VALUE
+-ossl_get_errors()
++ossl_get_errors(void)
+ {
+     VALUE ary;
+     long e;
+@@ -747,27 +748,27 @@ static void Init_ossl_locks(void)
+  *
+  * First set up the cipher for encryption
+  *
+- *   encrypter = OpenSSL::Cipher.new 'AES-128-CBC'
+- *   encrypter.encrypt
+- *   encrypter.pkcs5_keyivgen pass_phrase, salt
++ *   encryptor = OpenSSL::Cipher.new 'AES-128-CBC'
++ *   encryptor.encrypt
++ *   encryptor.pkcs5_keyivgen pass_phrase, salt
+  *
+  * Then pass the data you want to encrypt through
+  *
+- *   encrypted = encrypter.update 'top secret document'
+- *   encrypted << encrypter.final
++ *   encrypted = encryptor.update 'top secret document'
++ *   encrypted << encryptor.final
+  *
+  * === Decryption
+  *
+  * Use a new Cipher instance set up for decryption
+  *
+- *   decrypter = OpenSSL::Cipher.new 'AES-128-CBC'
+- *   decrypter.decrypt
+- *   decrypter.pkcs5_keyivgen pass_phrase, salt
++ *   decryptor = OpenSSL::Cipher.new 'AES-128-CBC'
++ *   decryptor.decrypt
++ *   decryptor.pkcs5_keyivgen pass_phrase, salt
+  *
+  * Then pass the data you want to decrypt through
+  *
+- *   plain = decrypter.update encrypted
+- *   plain << decrypter.final
++ *   plain = decryptor.update encrypted
++ *   plain << decryptor.final
+  *
+  * == X509 Certificates
+  *
+@@ -1033,7 +1034,7 @@ static void Init_ossl_locks(void)
+  *
+  */
+ void
+-Init_openssl_cms()
++Init_openssl_cms(void)
+ {
+     /*
+      * Init timezone info
+diff --git a/ext/openssl_cms/ossl.h b/ext/openssl_cms/ossl.h
+index 8ba08d7..6f1790e 100644
+--- a/ext/openssl_cms/ossl.h
++++ b/ext/openssl_cms/ossl.h
+@@ -138,8 +138,8 @@ VALUE ossl_x509name_sk2ary(STACK_OF(X509_NAME) *names);
+ VALUE ossl_buf2str(char *buf, int len);
+ #define ossl_str_adjust(str, p) \
+ do{\
+-    int len = RSTRING_LENINT(str);\
+-    int newlen = rb_long2int((p) - (unsigned char*)RSTRING_PTR(str));\
++    long len = RSTRING_LEN(str);\
++    long newlen = (long)((p) - (unsigned char*)RSTRING_PTR(str));\
+     assert(newlen <= len);\
+     rb_str_set_len((str), newlen);\
+ }while(0)
+diff --git a/ext/openssl_cms/ossl_asn1.c b/ext/openssl_cms/ossl_asn1.c
+index efdfbfc..3a24d17 100644
+--- a/ext/openssl_cms/ossl_asn1.c
++++ b/ext/openssl_cms/ossl_asn1.c
+@@ -495,7 +495,7 @@ typedef struct {
+     VALUE *klass;
+ } ossl_asn1_info_t;
+ 
+-static ossl_asn1_info_t ossl_asn1_info[] = {
++static const ossl_asn1_info_t ossl_asn1_info[] = {
+     { "EOC",               &cASN1EndOfContent,    },  /*  0 */
+     { "BOOLEAN",           &cASN1Boolean,         },  /*  1 */
+     { "INTEGER",           &cASN1Integer,         },  /*  2 */
+@@ -529,7 +529,7 @@ static ossl_asn1_info_t ossl_asn1_info[] = {
+     { "BMPSTRING",         &cASN1BMPString,       },  /* 30 */
+ };
+ 
+-int ossl_asn1_info_size = (sizeof(ossl_asn1_info)/sizeof(ossl_asn1_info[0]));
++enum {ossl_asn1_info_size = (sizeof(ossl_asn1_info)/sizeof(ossl_asn1_info[0]))};
+ 
+ static VALUE class_tag_map;
+ 
+@@ -1472,7 +1472,7 @@ OSSL_ASN1_IMPL_FACTORY_METHOD(Set)
+ OSSL_ASN1_IMPL_FACTORY_METHOD(EndOfContent)
+ 
+ void
+-Init_ossl_asn1()
++Init_ossl_asn1(void)
+ {
+     VALUE ary;
+     int i;
+diff --git a/ext/openssl_cms/ossl_bio.c b/ext/openssl_cms/ossl_bio.c
+index a11c08c..e150de0 100644
+--- a/ext/openssl_cms/ossl_bio.c
++++ b/ext/openssl_cms/ossl_bio.c
+@@ -18,7 +18,7 @@ ossl_obj2bio(VALUE obj)
+ {
+     BIO *bio;
+ 
+-    if (TYPE(obj) == T_FILE) {
++    if (RB_TYPE_P(obj, T_FILE)) {
+ 	rb_io_t *fptr;
+ 	FILE *fp;
+ 	int fd;
+diff --git a/ext/openssl_cms/ossl_bn.c b/ext/openssl_cms/ossl_bn.c
+index 0547363..58796fe 100644
+--- a/ext/openssl_cms/ossl_bn.c
++++ b/ext/openssl_cms/ossl_bn.c
+@@ -15,11 +15,11 @@
+   if (!(bn)) { \
+     ossl_raise(rb_eRuntimeError, "BN wasn't initialized!"); \
+   } \
+-  (obj) = Data_Wrap_Struct((klass), 0, BN_clear_free, (bn)); \
++  (obj) = TypedData_Wrap_Struct((klass), &ossl_bn_type, (bn)); \
+ } while (0)
+ 
+ #define GetBN(obj, bn) do { \
+-  Data_Get_Struct((obj), BIGNUM, (bn)); \
++  TypedData_Get_Struct((obj), BIGNUM, &ossl_bn_type, (bn)); \
+   if (!(bn)) { \
+     ossl_raise(rb_eRuntimeError, "BN wasn't initialized!"); \
+   } \
+@@ -30,6 +30,25 @@
+   GetBN((obj), (bn)); \
+ } while (0)
+ 
++static void
++ossl_bn_free(void *ptr)
++{
++    BN_clear_free(ptr);
++}
++
++static size_t
++ossl_bn_size(const void *ptr)
++{
++    return sizeof(BIGNUM);
++}
++
++static const rb_data_type_t ossl_bn_type = {
++    "OpenSSL/BN",
++    {0, ossl_bn_free, ossl_bn_size,},
++    0, 0,
++    RUBY_TYPED_FREE_IMMEDIATELY,
++};
++
+ /*
+  * Classes
+  */
+@@ -140,26 +159,24 @@ ossl_bn_initialize(int argc, VALUE *argv, VALUE self)
+ 	return self;
+     }
+     else if (RB_TYPE_P(str, T_BIGNUM)) {
+-	int i, j, len = RBIGNUM_LENINT(str);
+-	BDIGIT *ds = RBIGNUM_DIGITS(str);
++        size_t len = rb_absint_size(str, NULL);
++	unsigned char *bin;
+ 	VALUE buf;
+-	unsigned char *bin = (unsigned char*)ALLOCV_N(BDIGIT, buf, len);
+-
+-	for (i = 0; len > i; i++) {
+-	    BDIGIT v = ds[i];
+-	    for (j = SIZEOF_BDIGITS - 1; 0 <= j; j--) {
+-		bin[(len-1-i)*SIZEOF_BDIGITS+j] = v&0xff;
+-		v >>= 8;
+-	    }
+-	}
++        int sign;
++
++        if (INT_MAX < len) {
++            rb_raise(eBNError, "bignum too long");
++        }
++        bin = (unsigned char*)ALLOCV_N(unsigned char, buf, len);
++        sign = rb_integer_pack(str, bin, len, 1, 0, INTEGER_PACK_BIG_ENDIAN);
+ 
+ 	GetBN(self, bn);
+-	if (!BN_bin2bn(bin, (int)SIZEOF_BDIGITS*len, bn)) {
++	if (!BN_bin2bn(bin, (int)len, bn)) {
+ 	    ALLOCV_END(buf);
+ 	    ossl_raise(eBNError, NULL);
+ 	}
+ 	ALLOCV_END(buf);
+-	if (!RBIGNUM_SIGN(str)) BN_set_negative(bn, 1);
++	if (sign < 0) BN_set_negative(bn, 1);
+ 	return self;
+     }
+     if (RTEST(rb_obj_is_kind_of(str, cBN))) {
+@@ -775,7 +792,7 @@ ossl_bn_is_prime_fasttest(int argc, VALUE *argv, VALUE self)
+  * (NOTE: ordering of methods is the same as in 'man bn')
+  */
+ void
+-Init_ossl_bn()
++Init_ossl_bn(void)
+ {
+ #if 0
+     mOSSL = rb_define_module("OpenSSL"); /* let rdoc know about mOSSL */
+diff --git a/ext/openssl_cms/ossl_cipher.c b/ext/openssl_cms/ossl_cipher.c
+index 0fa740e..08fdacf 100644
+--- a/ext/openssl_cms/ossl_cipher.c
++++ b/ext/openssl_cms/ossl_cipher.c
+@@ -11,13 +11,13 @@
+ #include "ossl.h"
+ 
+ #define WrapCipher(obj, klass, ctx) \
+-    (obj) = Data_Wrap_Struct((klass), 0, ossl_cipher_free, (ctx))
++    (obj) = TypedData_Wrap_Struct((klass), &ossl_cipher_type, (ctx))
+ #define MakeCipher(obj, klass, ctx) \
+-    (obj) = Data_Make_Struct((klass), EVP_CIPHER_CTX, 0, ossl_cipher_free, (ctx))
++    (obj) = TypedData_Make_Struct((klass), EVP_CIPHER_CTX, &ossl_cipher_type, (ctx))
+ #define AllocCipher(obj, ctx) \
+-    memset(DATA_PTR(obj) = (ctx) = ALLOC(EVP_CIPHER_CTX), 0, sizeof(EVP_CIPHER_CTX))
++    (DATA_PTR(obj) = (ctx) = ZALLOC(EVP_CIPHER_CTX))
+ #define GetCipherInit(obj, ctx) do { \
+-    Data_Get_Struct((obj), EVP_CIPHER_CTX, (ctx)); \
++    TypedData_Get_Struct((obj), EVP_CIPHER_CTX, &ossl_cipher_type, (ctx)); \
+ } while (0)
+ #define GetCipher(obj, ctx) do { \
+     GetCipherInit((obj), (ctx)); \
+@@ -37,6 +37,15 @@ VALUE cCipher;
+ VALUE eCipherError;
+ 
+ static VALUE ossl_cipher_alloc(VALUE klass);
++static void ossl_cipher_free(void *ptr);
++static size_t ossl_cipher_memsize(const void *ptr);
++
++static const rb_data_type_t ossl_cipher_type = {
++    "OpenSSL/Cipher",
++    {0, ossl_cipher_free, ossl_cipher_memsize,},
++    0, 0,
++    RUBY_TYPED_FREE_IMMEDIATELY,
++};
+ 
+ /*
+  * PUBLIC
+@@ -70,14 +79,22 @@ ossl_cipher_new(const EVP_CIPHER *cipher)
+  * PRIVATE
+  */
+ static void
+-ossl_cipher_free(EVP_CIPHER_CTX *ctx)
++ossl_cipher_free(void *ptr)
+ {
++    EVP_CIPHER_CTX *ctx = ptr;
+     if (ctx) {
+ 	EVP_CIPHER_CTX_cleanup(ctx);
+ 	ruby_xfree(ctx);
+     }
+ }
+ 
++static size_t
++ossl_cipher_memsize(const void *ptr)
++{
++    const EVP_CIPHER_CTX *ctx = ptr;
++    return ctx ? sizeof(*ctx) : 0;
++}
++
+ static VALUE
+ ossl_cipher_alloc(VALUE klass)
+ {
+@@ -158,7 +175,7 @@ add_cipher_name_to_ary(const OBJ_NAME *name, VALUE ary)
+ #ifdef HAVE_OBJ_NAME_DO_ALL_SORTED
+ /*
+  *  call-seq:
+- *     Cipher.ciphers -> array[string...]
++ *     OpenSSL::Cipher.ciphers -> array[string...]
+  *
+  *  Returns the names of all available ciphers in an array.
+  */
+@@ -183,7 +200,7 @@ ossl_s_ciphers(VALUE self)
+  *     cipher.reset -> self
+  *
+  *  Fully resets the internal state of the Cipher. By using this, the same
+- *  Cipher instance may be used several times for en- or decryption tasks.
++ *  Cipher instance may be used several times for encryption or decryption tasks.
+  *
+  *  Internally calls EVP_CipherInit_ex(ctx, NULL, NULL, NULL, NULL, -1).
+  */
+diff --git a/ext/openssl_cms/ossl_config.c b/ext/openssl_cms/ossl_config.c
+index 0f25a19..74a52f7 100644
+--- a/ext/openssl_cms/ossl_config.c
++++ b/ext/openssl_cms/ossl_config.c
+@@ -17,7 +17,7 @@
+ VALUE cConfig;
+ /* Document-class: OpenSSL::ConfigError
+  *
+- * General error for openssl library configuration files. Including formating,
++ * General error for openssl library configuration files. Including formatting,
+  * parsing errors, etc.
+  */
+ VALUE eConfigError;
+@@ -69,7 +69,7 @@ GetConfigPtr(VALUE obj)
+  * INIT
+  */
+ void
+-Init_ossl_config()
++Init_ossl_config(void)
+ {
+     char *default_config_file;
+     eConfigError = rb_define_class_under(mOSSL, "ConfigError", eOSSLError);
+diff --git a/ext/openssl_cms/ossl_digest.c b/ext/openssl_cms/ossl_digest.c
+index fdf13e9..6ce5316 100644
+--- a/ext/openssl_cms/ossl_digest.c
++++ b/ext/openssl_cms/ossl_digest.c
+@@ -11,7 +11,7 @@
+ #include "ossl.h"
+ 
+ #define GetDigest(obj, ctx) do { \
+-    Data_Get_Struct((obj), EVP_MD_CTX, (ctx)); \
++    TypedData_Get_Struct((obj), EVP_MD_CTX, &ossl_digest_type, (ctx)); \
+     if (!(ctx)) { \
+ 	ossl_raise(rb_eRuntimeError, "Digest CTX wasn't initialized!"); \
+     } \
+@@ -29,6 +29,20 @@ VALUE eDigestError;
+ 
+ static VALUE ossl_digest_alloc(VALUE klass);
+ 
++static void
++ossl_digest_free(void *ctx)
++{
++    EVP_MD_CTX_destroy(ctx);
++}
++
++static const rb_data_type_t ossl_digest_type = {
++    "OpenSSL/Digest",
++    {
++	0, ossl_digest_free,
++    },
++    0, 0, RUBY_TYPED_FREE_IMMEDIATELY,
++};
++
+ /*
+  * Public
+  */
+@@ -38,7 +52,7 @@ GetDigestPtr(VALUE obj)
+     const EVP_MD *md;
+     ASN1_OBJECT *oid = NULL;
+ 
+-    if (TYPE(obj) == T_STRING) {
++    if (RB_TYPE_P(obj, T_STRING)) {
+     	const char *name = StringValueCStr(obj);
+ 
+ 	md = EVP_get_digestbyname(name);
+@@ -87,7 +101,7 @@ ossl_digest_alloc(VALUE klass)
+     ctx = EVP_MD_CTX_create();
+     if (ctx == NULL)
+ 	ossl_raise(rb_eRuntimeError, "EVP_MD_CTX_create() failed");
+-    obj = Data_Wrap_Struct(klass, 0, EVP_MD_CTX_destroy, ctx);
++    obj = TypedData_Wrap_Struct(klass, &ossl_digest_type, ctx);
+ 
+     return obj;
+ }
+@@ -294,7 +308,7 @@ ossl_digest_block_length(VALUE self)
+  * INIT
+  */
+ void
+-Init_ossl_digest()
++Init_ossl_digest(void)
+ {
+     rb_require("digest");
+ 
+diff --git a/ext/openssl_cms/ossl_engine.c b/ext/openssl_cms/ossl_engine.c
+index da1a3c7..04b5879 100644
+--- a/ext/openssl_cms/ossl_engine.c
++++ b/ext/openssl_cms/ossl_engine.c
+@@ -16,10 +16,10 @@
+     if (!(engine)) { \
+ 	ossl_raise(rb_eRuntimeError, "ENGINE wasn't initialized."); \
+     } \
+-    (obj) = Data_Wrap_Struct((klass), 0, ENGINE_free, (engine)); \
++    (obj) = TypedData_Wrap_Struct((klass), &ossl_engine_type, (engine)); \
+ } while(0)
+ #define GetEngine(obj, engine) do { \
+-    Data_Get_Struct((obj), ENGINE, (engine)); \
++    TypedData_Get_Struct((obj), ENGINE, &ossl_engine_type, (engine)); \
+     if (!(engine)) { \
+         ossl_raise(rb_eRuntimeError, "ENGINE wasn't initialized."); \
+     } \
+@@ -57,6 +57,20 @@ do{\
+   }\
+ }while(0)
+ 
++static void
++ossl_engine_free(void *engine)
++{
++    ENGINE_free(engine);
++}
++
++static const rb_data_type_t ossl_engine_type = {
++    "OpenSSL/Engine",
++    {
++	0, ossl_engine_free,
++    },
++    0, 0, RUBY_TYPED_FREE_IMMEDIATELY,
++};
++
+ /* Document-method: OpenSSL::Engine.load
+  *
+  * call-seq:
+@@ -523,24 +537,17 @@ ossl_engine_get_cmds(VALUE self)
+ static VALUE
+ ossl_engine_inspect(VALUE self)
+ {
+-    VALUE str;
+-    const char *cname = rb_class2name(rb_obj_class(self));
+-
+-    str = rb_str_new2("#<");
+-    rb_str_cat2(str, cname);
+-    rb_str_cat2(str, " id=\"");
+-    rb_str_append(str, ossl_engine_get_id(self));
+-    rb_str_cat2(str, "\" name=\"");
+-    rb_str_append(str, ossl_engine_get_name(self));
+-    rb_str_cat2(str, "\">");
+-
+-    return str;
++    ENGINE *e;
++
++    GetEngine(self, e);
++    return rb_sprintf("#<%"PRIsVALUE" id=\"%s\" name=\"%s\">",
++		      rb_obj_class(self), ENGINE_get_id(e), ENGINE_get_name(e));
+ }
+ 
+ #define DefEngineConst(x) rb_define_const(cEngine, #x, INT2NUM(ENGINE_##x))
+ 
+ void
+-Init_ossl_engine()
++Init_ossl_engine(void)
+ {
+     cEngine = rb_define_class_under(mOSSL, "Engine", rb_cObject);
+     eEngineError = rb_define_class_under(cEngine, "EngineError", eOSSLError);
+@@ -585,7 +592,7 @@ Init_ossl_engine()
+ }
+ #else
+ void
+-Init_ossl_engine()
++Init_ossl_engine(void)
+ {
+ }
+ #endif
+diff --git a/ext/openssl_cms/ossl_hmac.c b/ext/openssl_cms/ossl_hmac.c
+index 0bba44d..74fc962 100644
+--- a/ext/openssl_cms/ossl_hmac.c
++++ b/ext/openssl_cms/ossl_hmac.c
+@@ -13,9 +13,9 @@
+ #include "ossl.h"
+ 
+ #define MakeHMAC(obj, klass, ctx) \
+-    (obj) = Data_Make_Struct((klass), HMAC_CTX, 0, ossl_hmac_free, (ctx))
++    (obj) = TypedData_Make_Struct((klass), HMAC_CTX, &ossl_hmac_type, (ctx))
+ #define GetHMAC(obj, ctx) do { \
+-    Data_Get_Struct((obj), HMAC_CTX, (ctx)); \
++    TypedData_Get_Struct((obj), HMAC_CTX, &ossl_hmac_type, (ctx)); \
+     if (!(ctx)) { \
+ 	ossl_raise(rb_eRuntimeError, "HMAC wasn't initialized"); \
+     } \
+@@ -39,12 +39,20 @@ VALUE eHMACError;
+  * Private
+  */
+ static void
+-ossl_hmac_free(HMAC_CTX *ctx)
++ossl_hmac_free(void *ctx)
+ {
+     HMAC_CTX_cleanup(ctx);
+     ruby_xfree(ctx);
+ }
+ 
++static const rb_data_type_t ossl_hmac_type = {
++    "OpenSSL/HMAC",
++    {
++	0, ossl_hmac_free,
++    },
++    0, 0, RUBY_TYPED_FREE_IMMEDIATELY,
++};
++
+ static VALUE
+ ossl_hmac_alloc(VALUE klass)
+ {
+@@ -327,7 +335,7 @@ ossl_hmac_s_hexdigest(VALUE klass, VALUE digest, VALUE key, VALUE data)
+  * INIT
+  */
+ void
+-Init_ossl_hmac()
++Init_ossl_hmac(void)
+ {
+ #if 0
+     /* :nodoc: */
+@@ -357,8 +365,8 @@ Init_ossl_hmac()
+ #else /* NO_HMAC */
+ #  warning >>> OpenSSL is compiled without HMAC support <<<
+ void
+-Init_ossl_hmac()
++Init_ossl_hmac(void)
+ {
+-    rb_warning("HMAC will NOT be avaible: OpenSSL is compiled without HMAC.");
++    rb_warning("HMAC is not available: OpenSSL is compiled without HMAC.");
+ }
+ #endif /* NO_HMAC */
+diff --git a/ext/openssl_cms/ossl_ns_spki.c b/ext/openssl_cms/ossl_ns_spki.c
+index b80984c..d2a52e6 100644
+--- a/ext/openssl_cms/ossl_ns_spki.c
++++ b/ext/openssl_cms/ossl_ns_spki.c
+@@ -14,10 +14,10 @@
+     if (!(spki)) { \
+ 	ossl_raise(rb_eRuntimeError, "SPKI wasn't initialized!"); \
+     } \
+-    (obj) = Data_Wrap_Struct((klass), 0, NETSCAPE_SPKI_free, (spki)); \
++    (obj) = TypedData_Wrap_Struct((klass), &ossl_netscape_spki_type, (spki)); \
+ } while (0)
+ #define GetSPKI(obj, spki) do { \
+-    Data_Get_Struct((obj), NETSCAPE_SPKI, (spki)); \
++    TypedData_Get_Struct((obj), NETSCAPE_SPKI, &ossl_netscape_spki_type, (spki)); \
+     if (!(spki)) { \
+ 	ossl_raise(rb_eRuntimeError, "SPKI wasn't initialized!"); \
+     } \
+@@ -37,6 +37,21 @@ VALUE eSPKIError;
+ /*
+  * Private functions
+  */
++
++static void
++ossl_netscape_spki_free(void *spki)
++{
++    NETSCAPE_SPKI_free(spki);
++}
++
++static const rb_data_type_t ossl_netscape_spki_type = {
++    "OpenSSL/NETSCAPE_SPKI",
++    {
++	0, ossl_netscape_spki_free,
++    },
++    0, 0, RUBY_TYPED_FREE_IMMEDIATELY,
++};
++
+ static VALUE
+ ossl_spki_alloc(VALUE klass)
+ {
+@@ -360,7 +375,7 @@ ossl_spki_verify(VALUE self, VALUE key)
+  */
+ 
+ void
+-Init_ossl_ns_spki()
++Init_ossl_ns_spki(void)
+ {
+ #if 0
+     mOSSL = rb_define_module("OpenSSL"); /* let rdoc know about mOSSL */
+diff --git a/ext/openssl_cms/ossl_ocsp.c b/ext/openssl_cms/ossl_ocsp.c
+index 4e2e839..dc31d79 100644
+--- a/ext/openssl_cms/ossl_ocsp.c
++++ b/ext/openssl_cms/ossl_ocsp.c
+@@ -15,10 +15,10 @@
+ 
+ #define WrapOCSPReq(klass, obj, req) do { \
+     if(!(req)) ossl_raise(rb_eRuntimeError, "Request wasn't initialized!"); \
+-    (obj) = Data_Wrap_Struct((klass), 0, OCSP_REQUEST_free, (req)); \
++    (obj) = TypedData_Wrap_Struct((klass), &ossl_ocsp_request_type, (req)); \
+ } while (0)
+ #define GetOCSPReq(obj, req) do { \
+-    Data_Get_Struct((obj), OCSP_REQUEST, (req)); \
++    TypedData_Get_Struct((obj), OCSP_REQUEST, &ossl_ocsp_request_type, (req)); \
+     if(!(req)) ossl_raise(rb_eRuntimeError, "Request wasn't initialized!"); \
+ } while (0)
+ #define SafeGetOCSPReq(obj, req) do { \
+@@ -28,10 +28,10 @@
+ 
+ #define WrapOCSPRes(klass, obj, res) do { \
+     if(!(res)) ossl_raise(rb_eRuntimeError, "Response wasn't initialized!"); \
+-    (obj) = Data_Wrap_Struct((klass), 0, OCSP_RESPONSE_free, (res)); \
++    (obj) = TypedData_Wrap_Struct((klass), &ossl_ocsp_response_type, (res)); \
+ } while (0)
+ #define GetOCSPRes(obj, res) do { \
+-    Data_Get_Struct((obj), OCSP_RESPONSE, (res)); \
++    TypedData_Get_Struct((obj), OCSP_RESPONSE, &ossl_ocsp_response_type, (res)); \
+     if(!(res)) ossl_raise(rb_eRuntimeError, "Response wasn't initialized!"); \
+ } while (0)
+ #define SafeGetOCSPRes(obj, res) do { \
+@@ -41,10 +41,10 @@
+ 
+ #define WrapOCSPBasicRes(klass, obj, res) do { \
+     if(!(res)) ossl_raise(rb_eRuntimeError, "Response wasn't initialized!"); \
+-    (obj) = Data_Wrap_Struct((klass), 0, OCSP_BASICRESP_free, (res)); \
++    (obj) = TypedData_Wrap_Struct((klass), &ossl_ocsp_basicresp_type, (res)); \
+ } while (0)
+ #define GetOCSPBasicRes(obj, res) do { \
+-    Data_Get_Struct((obj), OCSP_BASICRESP, (res)); \
++    TypedData_Get_Struct((obj), OCSP_BASICRESP, &ossl_ocsp_basicresp_type, (res)); \
+     if(!(res)) ossl_raise(rb_eRuntimeError, "Response wasn't initialized!"); \
+ } while (0)
+ #define SafeGetOCSPBasicRes(obj, res) do { \
+@@ -54,10 +54,10 @@
+ 
+ #define WrapOCSPCertId(klass, obj, cid) do { \
+     if(!(cid)) ossl_raise(rb_eRuntimeError, "Cert ID wasn't initialized!"); \
+-    (obj) = Data_Wrap_Struct((klass), 0, OCSP_CERTID_free, (cid)); \
++    (obj) = TypedData_Wrap_Struct((klass), &ossl_ocsp_certid_type, (cid)); \
+ } while (0)
+ #define GetOCSPCertId(obj, cid) do { \
+-    Data_Get_Struct((obj), OCSP_CERTID, (cid)); \
++    TypedData_Get_Struct((obj), OCSP_CERTID, &ossl_ocsp_certid_type, (cid)); \
+     if(!(cid)) ossl_raise(rb_eRuntimeError, "Cert ID wasn't initialized!"); \
+ } while (0)
+ #define SafeGetOCSPCertId(obj, cid) do { \
+@@ -72,6 +72,62 @@ VALUE cOCSPRes;
+ VALUE cOCSPBasicRes;
+ VALUE cOCSPCertId;
+ 
++static void
++ossl_ocsp_request_free(void *ptr)
++{
++    OCSP_REQUEST_free(ptr);
++}
++
++static const rb_data_type_t ossl_ocsp_request_type = {
++    "OpenSSL/OCSP/REQUEST",
++    {
++	0, ossl_ocsp_request_free,
++    },
++    0, 0, RUBY_TYPED_FREE_IMMEDIATELY,
++};
++
++static void
++ossl_ocsp_response_free(void *ptr)
++{
++    OCSP_RESPONSE_free(ptr);
++}
++
++static const rb_data_type_t ossl_ocsp_response_type = {
++    "OpenSSL/OCSP/RESPONSE",
++    {
++	0, ossl_ocsp_response_free,
++    },
++    0, 0, RUBY_TYPED_FREE_IMMEDIATELY,
++};
++
++static void
++ossl_ocsp_basicresp_free(void *ptr)
++{
++    OCSP_BASICRESP_free(ptr);
++}
++
++static const rb_data_type_t ossl_ocsp_basicresp_type = {
++    "OpenSSL/OCSP/BASICRESP",
++    {
++	0, ossl_ocsp_basicresp_free,
++    },
++    0, 0, RUBY_TYPED_FREE_IMMEDIATELY,
++};
++
++static void
++ossl_ocsp_certid_free(void *ptr)
++{
++    OCSP_CERTID_free(ptr);
++}
++
++static const rb_data_type_t ossl_ocsp_certid_type = {
++    "OpenSSL/OCSP/CERTID",
++    {
++	0, ossl_ocsp_certid_free,
++    },
++    0, 0, RUBY_TYPED_FREE_IMMEDIATELY,
++};
++
+ /*
+  * Public
+  */
+@@ -99,6 +155,15 @@ ossl_ocspreq_alloc(VALUE klass)
+     return obj;
+ }
+ 
++/*
++ * call-seq:
++ *   OpenSSL::OCSP::Request.new              -> request
++ *   OpenSSL::OCSP::Request.new(request_der) -> request
++ *
++ * Creates a new OpenSSL::OCSP::Request.  The request may be created empty or
++ * from a +request_der+ string.
++ */
++
+ static VALUE
+ ossl_ocspreq_initialize(int argc, VALUE *argv, VALUE self)
+ {
+@@ -121,6 +186,17 @@ ossl_ocspreq_initialize(int argc, VALUE *argv, VALUE self)
+     return self;
+ }
+ 
++/*
++ * call-seq:
++ *   request.add_nonce(nonce = nil) -> request
++ *
++ * Adds a +nonce+ to the OCSP request.  If no nonce is given a random one will
++ * be generated.
++ *
++ * The nonce is used to prevent replay attacks but some servers do not support
++ * it.
++ */
++
+ static VALUE
+ ossl_ocspreq_add_nonce(int argc, VALUE *argv, VALUE self)
+ {
+@@ -143,18 +219,25 @@ ossl_ocspreq_add_nonce(int argc, VALUE *argv, VALUE self)
+     return self;
+ }
+ 
+-/* Check nonce validity in a request and response.
+- * Return value reflects result:
+- *  1: nonces present and equal.
+- *  2: nonces both absent.
+- *  3: nonce present in response only.
+- *  0: nonces both present and not equal.
+- *  -1: nonce in request only.
++/*
++ * call-seq:
++ *   request.check_nonce(response) -> result
++ *
++ * Checks the nonce validity for this request and +response+.
++ *
++ * The return value is one of the following:
+  *
+- *  For most responders clients can check return > 0.
+- *  If responder doesn't handle nonces return != 0 may be
+- *  necessary. return == 0 is always an error.
++ * -1 :: nonce in request only.
++ *  0 :: nonces both present and not equal.
++ *  1 :: nonces present and equal.
++ *  2 :: nonces both absent.
++ *  3 :: nonce present in response only.
++ *
++ * For most responses, clients can check +result+ > 0.  If a responder doesn't
++ * handle nonces <code>result.nonzero?</code> may be necessary.  A result of
++ * <code>0</code> is always an error.
+  */
++
+ static VALUE
+ ossl_ocspreq_check_nonce(VALUE self, VALUE basic_resp)
+ {
+@@ -169,6 +252,13 @@ ossl_ocspreq_check_nonce(VALUE self, VALUE basic_resp)
+     return INT2NUM(res);
+ }
+ 
++/*
++ * call-seq:
++ *   request.add_certid(certificate_id) -> request
++ *
++ * Adds +certificate_id+ to the request.
++ */
++
+ static VALUE
+ ossl_ocspreq_add_certid(VALUE self, VALUE certid)
+ {
+@@ -183,6 +273,13 @@ ossl_ocspreq_add_certid(VALUE self, VALUE certid)
+     return self;
+ }
+ 
++/*
++ * call-seq:
++ *   request.certid -> [certificate_id, ...]
++ *
++ * Returns all certificate IDs in this request.
++ */
++
+ static VALUE
+ ossl_ocspreq_get_certid(VALUE self)
+ {
+@@ -206,6 +303,17 @@ ossl_ocspreq_get_certid(VALUE self)
+     return ary;
+ }
+ 
++/*
++ * call-seq:
++ *   request.sign(signer_cert, signer_key)                      -> self
++ *   request.sign(signer_cert, signer_key, certificates)        -> self
++ *   request.sign(signer_cert, signer_key, certificates, flags) -> self
++ *
++ * Signs this OCSP request using +signer_cert+ and +signer_key+.
++ * +certificates+ is an optional Array of certificates that may be included in
++ * the request.
++ */
++
+ static VALUE
+ ossl_ocspreq_sign(int argc, VALUE *argv, VALUE self)
+ {
+@@ -234,6 +342,14 @@ ossl_ocspreq_sign(int argc, VALUE *argv, VALUE self)
+     return self;
+ }
+ 
++/*
++ * call-seq:
++ *   request.verify(certificates, store)        -> true or false
++ *   request.verify(certificates, store, flags) -> true or false
++ *
++ * Verifies this request using the given +certificates+ and X509 +store+.
++ */
++
+ static VALUE
+ ossl_ocspreq_verify(int argc, VALUE *argv, VALUE self)
+ {
+@@ -255,6 +371,10 @@ ossl_ocspreq_verify(int argc, VALUE *argv, VALUE self)
+     return result ? Qtrue : Qfalse;
+ }
+ 
++/*
++ * Returns this request as a DER-encoded string
++ */
++
+ static VALUE
+ ossl_ocspreq_to_der(VALUE self)
+ {
+@@ -278,6 +398,13 @@ ossl_ocspreq_to_der(VALUE self)
+ /*
+  * OCSP::Response
+  */
++
++/* call-seq:
++ *   OpenSSL::OCSP::Response.create(status, basic_response = nil) -> response
++ *
++ * Creates an OpenSSL::OCSP::Response from +status+ and +basic_response+.
++ */
++
+ static VALUE
+ ossl_ocspres_s_create(VALUE klass, VALUE status, VALUE basic_resp)
+ {
+@@ -308,6 +435,15 @@ ossl_ocspres_alloc(VALUE klass)
+     return obj;
+ }
+ 
++/*
++ * call-seq:
++ *   OpenSSL::OCSP::Response.new               -> response
++ *   OpenSSL::OCSP::Response.new(response_der) -> response
++ *
++ * Creates a new OpenSSL::OCSP::Response.  The response may be created empty or
++ * from a +response_der+ string.
++ */
++
+ static VALUE
+ ossl_ocspres_initialize(int argc, VALUE *argv, VALUE self)
+ {
+@@ -330,6 +466,13 @@ ossl_ocspres_initialize(int argc, VALUE *argv, VALUE self)
+     return self;
+ }
+ 
++/*
++ * call-seq:
++ *   response.status -> Integer
++ *
++ * Returns the status of the response.
++ */
++
+ static VALUE
+ ossl_ocspres_status(VALUE self)
+ {
+@@ -342,6 +485,13 @@ ossl_ocspres_status(VALUE self)
+     return INT2NUM(st);
+ }
+ 
++/*
++ * call-seq:
++ *   response.status_string -> String
++ *
++ * Returns a status string for the response.
++ */
++
+ static VALUE
+ ossl_ocspres_status_string(VALUE self)
+ {
+@@ -354,6 +504,13 @@ ossl_ocspres_status_string(VALUE self)
+     return rb_str_new2(OCSP_response_status_str(st));
+ }
+ 
++/*
++ * call-seq:
++ *   response.basic
++ *
++ * Returns a BasicResponse for this response
++ */
++
+ static VALUE
+ ossl_ocspres_get_basic(VALUE self)
+ {
+@@ -369,6 +526,13 @@ ossl_ocspres_get_basic(VALUE self)
+     return ret;
+ }
+ 
++/*
++ * call-seq:
++ *   response.to_der -> String
++ *
++ * Returns this response as a DER-encoded string.
++ */
++
+ static VALUE
+ ossl_ocspres_to_der(VALUE self)
+ {
+@@ -405,12 +569,27 @@ ossl_ocspbres_alloc(VALUE klass)
+     return obj;
+ }
+ 
++/*
++ * call-seq:
++ *   OpenSSL::OCSP::BasicResponse.new(*) -> basic_response
++ *
++ * Creates a new BasicResponse and ignores all arguments.
++ */
++
+ static VALUE
+ ossl_ocspbres_initialize(int argc, VALUE *argv, VALUE self)
+ {
+     return self;
+ }
+ 
++/*
++ * call-seq:
++ *   basic_response.copy_nonce(request) -> Integer
++ *
++ * Copies the nonce from +request+ into this response.  Returns 1 on success
++ * and 0 on failure.
++ */
++
+ static VALUE
+ ossl_ocspbres_copy_nonce(VALUE self, VALUE request)
+ {
+@@ -425,6 +604,14 @@ ossl_ocspbres_copy_nonce(VALUE self, VALUE request)
+     return INT2NUM(ret);
+ }
+ 
++/*
++ * call-seq:
++ *   basic_response.add_nonce(nonce = nil)
++ *
++ * Adds +nonce+ to this response.  If no nonce was provided a random nonce
++ * will be added.
++ */
++
+ static VALUE
+ ossl_ocspbres_add_nonce(int argc, VALUE *argv, VALUE self)
+ {
+@@ -447,6 +634,22 @@ ossl_ocspbres_add_nonce(int argc, VALUE *argv, VALUE self)
+     return self;
+ }
+ 
++/*
++ * call-seq:
++ *   basic_response.add_status(certificate_id, status, reason, revocation_time, this_update, next_update, extensions) -> basic_response
++ *
++ * Adds a validation +status+ (0 for revoked, 1 for success) to this
++ * response for +certificate_id+.  +reason+ describes the reason for the
++ * revocation, if any.
++ *
++ * The +revocation_time+, +this_update+ and +next_update+ are times for the
++ * certificate's revocation time, the time of this status and the next update
++ * time for a new status, respectively.
++ *
++ * +extensions+ may be an Array of OpenSSL::X509::Extension that will
++ * be added to this response or nil.
++ */
++
+ static VALUE
+ ossl_ocspbres_add_status(VALUE self, VALUE cid, VALUE status,
+ 			 VALUE reason, VALUE revtime,
+@@ -515,6 +718,16 @@ ossl_ocspbres_add_status(VALUE self, VALUE cid, VALUE status,
+     return self;
+ }
+ 
++/*
++ * call-seq:
++ *   basic_response.status -> statuses
++ *
++ * Returns an Array of statuses for this response.  Each status contains a
++ * CertificateId, the status (0 for success, 1 for revoked), the reason for
++ * the status, the revocation time, the time of this update, the time for the
++ * next update and a list of OpenSSL::X509::Extensions.
++ */
++
+ static VALUE
+ ossl_ocspbres_get_status(VALUE self)
+ {
+@@ -560,6 +773,16 @@ ossl_ocspbres_get_status(VALUE self)
+     return ret;
+ }
+ 
++/*
++ * call-seq:
++ *   basic_response.sign(signer_cert, signer_key) -> self
++ *   basic_response.sign(signer_cert, signer_key, certificates) -> self
++ *   basic_response.sign(signer_cert, signer_key, certificates, flags) -> self
++ *
++ * Signs this response using the +signer_cert+ and +signer_key+.  Additional
++ * +certificates+ may be added to the signature along with a set of +flags+.
++ */
++
+ static VALUE
+ ossl_ocspbres_sign(int argc, VALUE *argv, VALUE self)
+ {
+@@ -590,6 +813,14 @@ ossl_ocspbres_sign(int argc, VALUE *argv, VALUE self)
+     return self;
+ }
+ 
++/*
++ * call-seq:
++ *   basic_response.verify(certificates, store) -> true or false
++ *   basic_response.verify(certificates, store, flags) -> true or false
++ *
++ * Verifies the signature of the response using the given +certificates+,
++ * +store+ and +flags+.
++ */
+ static VALUE
+ ossl_ocspbres_verify(int argc, VALUE *argv, VALUE self)
+ {
+@@ -627,6 +858,15 @@ ossl_ocspcid_alloc(VALUE klass)
+     return obj;
+ }
+ 
++/*
++ * call-seq:
++ *   OpenSSL::OCSP::CertificateId.new(subject, issuer, digest = nil) -> certificate_id
++ *
++ * Creates a new OpenSSL::OCSP::CertificateId for the given +subject+ and
++ * +issuer+ X509 certificates.  The +digest+ is used to compute the
++ * certificate ID and must be an OpenSSL::Digest instance.
++ */
++
+ static VALUE
+ ossl_ocspcid_initialize(int argc, VALUE *argv, VALUE self)
+ {
+@@ -657,6 +897,13 @@ ossl_ocspcid_initialize(int argc, VALUE *argv, VALUE self)
+     return self;
+ }
+ 
++/*
++ * call-seq:
++ *   certificate_id.cmp(other) -> true or false
++ *
++ * Compares this certificate id with +other+ and returns true if they are the
++ * same.
++ */
+ static VALUE
+ ossl_ocspcid_cmp(VALUE self, VALUE other)
+ {
+@@ -670,6 +917,14 @@ ossl_ocspcid_cmp(VALUE self, VALUE other)
+     return (result == 0) ? Qtrue : Qfalse;
+ }
+ 
++/*
++ * call-seq:
++ *   certificate_id.cmp_issuer(other) -> true or false
++ *
++ * Compares this certificate id's issuer with +other+ and returns true if
++ * they are the same.
++ */
++
+ static VALUE
+ ossl_ocspcid_cmp_issuer(VALUE self, VALUE other)
+ {
+@@ -683,6 +938,13 @@ ossl_ocspcid_cmp_issuer(VALUE self, VALUE other)
+     return (result == 0) ? Qtrue : Qfalse;
+ }
+ 
++/*
++ * call-seq:
++ *   certificate_id.get_serial -> Integer
++ *
++ * Returns the serial number of the issuing certificate.
++ */
++
+ static VALUE
+ ossl_ocspcid_get_serial(VALUE self)
+ {
+@@ -694,12 +956,132 @@ ossl_ocspcid_get_serial(VALUE self)
+ }
+ 
+ void
+-Init_ossl_ocsp()
++Init_ossl_ocsp(void)
+ {
++    /*
++     * OpenSSL::OCSP implements Online Certificate Status Protocol requests
++     * and responses.
++     *
++     * Creating and sending an OCSP request requires a subject certificate
++     * that contains an OCSP URL in an authorityInfoAccess extension and the
++     * issuer certificate for the subject certificate.  First, load the issuer
++     * and subject certificates:
++     *
++     *   subject = OpenSSL::X509::Certificate.new subject_pem
++     *   issuer  = OpenSSL::X509::Certificate.new issuer_pem
++     *
++     * To create the request we need to create a certificate ID for the
++     * subject certificate so the CA knows which certificate we are asking
++     * about:
++     *
++     *   digest = OpenSSL::Digest::SHA1.new
++     *   certificate_id =
++     *     OpenSSL::OCSP::CertificateId.new subject, issuer, digest
++     *
++     * Then create a request and add the certificate ID to it:
++     *
++     *   request = OpenSSL::OCSP::Request.new
++     *   request.add_certid certificate_id
++     *
++     * Adding a nonce to the request protects against replay attacks but not
++     * all CA process the nonce.
++     *
++     *   request.add_nonce
++     *
++     * To submit the request to the CA for verification we need to extract the
++     * OCSP URI from the subject certificate:
++     *
++     *   authority_info_access = subject.extensions.find do |extension|
++     *     extension.oid == 'authorityInfoAccess'
++     *   end
++     *
++     *   descriptions = authority_info_access.value.split "\n"
++     *   ocsp = descriptions.find do |description|
++     *     description.start_with? 'OCSP'
++     *   end
++     *
++     *   require 'uri'
++     *
++     *   ocsp_uri = URI ocsp[/URI:(.*)/, 1]
++     *
++     * To submit the request we'll POST the request to the OCSP URI (per RFC
++     * 2560).  Note that we only handle HTTP requests and don't handle any
++     * redirects in this example, so this is insufficient for serious use.
++     *
++     *   require 'net/http'
++     *
++     *   http_response =
++     *     Net::HTTP.start ocsp_uri.hostname, ocsp.port do |http|
++     *       http.post ocsp_uri.path, request.to_der,
++     *                 'content-type' => 'application/ocsp-request'
++     *   end
++     *
++     *   response = OpenSSL::OCSP::Response.new http_response.body
++     *   response_basic = response.basic
++     *
++     * First we check if the response has a valid signature.  Without a valid
++     * signature we cannot trust it.  If you get a failure here you may be
++     * missing a system certificate store or may be missing the intermediate
++     * certificates.
++     *
++     *   store = OpenSSL::X509::Store.new
++     *   store.set_default_paths
++     *
++     *   unless response.verify [], store then
++     *     raise 'response is not signed by a trusted certificate'
++     *   end
++     *
++     * The response contains the status information (success/fail).  We can
++     * display the status as a string:
++     *
++     *   puts response.status_string #=> successful
++     *
++     * Next we need to know the response details to determine if the response
++     * matches our request.  First we check the nonce.  Again, not all CAs
++     * support a nonce.  See Request#check_nonce for the meanings of the
++     * return values.
++     *
++     *   p request.check_nonce basic_response #=> value from -1 to 3
++     *
++     * Then extract the status information from the basic response.  (You can
++     * check multiple certificates in a request, but for this example we only
++     * submitted one.)
++     *
++     *   response_certificate_id, status, reason, revocation_time,
++     *     this_update, next_update, extensions = basic_response.status
++     *
++     * Then check the various fields.
++     *
++     *   unless response_certificate_id == certificate_id then
++     *     raise 'certificate id mismatch'
++     *   end
++     *
++     *   now = Time.now
++     *
++     *   if this_update > now then
++     *     raise 'update date is in the future'
++     *   end
++     *
++     *   if now > next_update then
++     *     raise 'next update time has passed'
++     *   end
++     */
++
+     mOCSP = rb_define_module_under(mOSSL, "OCSP");
+ 
++    /*
++     * OCSP error class.
++     */
++
+     eOCSPError = rb_define_class_under(mOCSP, "OCSPError", eOSSLError);
+ 
++    /*
++     * An OpenSSL::OCSP::Request contains the certificate information for
++     * determining if a certificate has been revoked or not.  A Request can be
++     * created for a certificate or from a DER-encoded request created
++     * elsewhere.
++     */
++
+     cOCSPReq = rb_define_class_under(mOCSP, "Request", rb_cObject);
+     rb_define_alloc_func(cOCSPReq, ossl_ocspreq_alloc);
+     rb_define_method(cOCSPReq, "initialize", ossl_ocspreq_initialize, -1);
+@@ -711,6 +1093,11 @@ Init_ossl_ocsp()
+     rb_define_method(cOCSPReq, "verify", ossl_ocspreq_verify, -1);
+     rb_define_method(cOCSPReq, "to_der", ossl_ocspreq_to_der, 0);
+ 
++    /*
++     * An OpenSSL::OCSP::Response contains the status of a certificate check
++     * which is created from an OpenSSL::OCSP::Request.
++     */
++
+     cOCSPRes = rb_define_class_under(mOCSP, "Response", rb_cObject);
+     rb_define_singleton_method(cOCSPRes, "create", ossl_ocspres_s_create, 2);
+     rb_define_alloc_func(cOCSPRes, ossl_ocspres_alloc);
+@@ -720,6 +1107,12 @@ Init_ossl_ocsp()
+     rb_define_method(cOCSPRes, "basic", ossl_ocspres_get_basic, 0);
+     rb_define_method(cOCSPRes, "to_der", ossl_ocspres_to_der, 0);
+ 
++    /*
++     * An OpenSSL::OCSP::BasicResponse contains the status of a certificate
++     * check which is created from an OpenSSL::OCSP::Request.  A
++     * BasicResponse is more detailed than a Response.
++     */
++
+     cOCSPBasicRes = rb_define_class_under(mOCSP, "BasicResponse", rb_cObject);
+     rb_define_alloc_func(cOCSPBasicRes, ossl_ocspbres_alloc);
+     rb_define_method(cOCSPBasicRes, "initialize", ossl_ocspbres_initialize, -1);
+@@ -730,6 +1123,11 @@ Init_ossl_ocsp()
+     rb_define_method(cOCSPBasicRes, "sign", ossl_ocspbres_sign, -1);
+     rb_define_method(cOCSPBasicRes, "verify", ossl_ocspbres_verify, -1);
+ 
++    /*
++     * An OpenSSL::OCSP::CertificateId identifies a certificate to the CA so
++     * that a status check can be performed.
++     */
++
+     cOCSPCertId = rb_define_class_under(mOCSP, "CertificateId", rb_cObject);
+     rb_define_alloc_func(cOCSPCertId, ossl_ocspcid_alloc);
+     rb_define_method(cOCSPCertId, "initialize", ossl_ocspcid_initialize, -1);
+@@ -737,50 +1135,110 @@ Init_ossl_ocsp()
+     rb_define_method(cOCSPCertId, "cmp_issuer", ossl_ocspcid_cmp_issuer, 1);
+     rb_define_method(cOCSPCertId, "serial", ossl_ocspcid_get_serial, 0);
+ 
+-#define DefOCSPConst(x) rb_define_const(mOCSP, #x, INT2NUM(OCSP_##x))
+-
+-    DefOCSPConst(RESPONSE_STATUS_SUCCESSFUL);
+-    DefOCSPConst(RESPONSE_STATUS_MALFORMEDREQUEST);
+-    DefOCSPConst(RESPONSE_STATUS_INTERNALERROR);
+-    DefOCSPConst(RESPONSE_STATUS_TRYLATER);
+-    DefOCSPConst(RESPONSE_STATUS_SIGREQUIRED);
+-    DefOCSPConst(RESPONSE_STATUS_UNAUTHORIZED);
+-
+-    DefOCSPConst(REVOKED_STATUS_NOSTATUS);
+-    DefOCSPConst(REVOKED_STATUS_UNSPECIFIED);
+-    DefOCSPConst(REVOKED_STATUS_KEYCOMPROMISE);
+-    DefOCSPConst(REVOKED_STATUS_CACOMPROMISE);
+-    DefOCSPConst(REVOKED_STATUS_AFFILIATIONCHANGED);
+-    DefOCSPConst(REVOKED_STATUS_SUPERSEDED);
+-    DefOCSPConst(REVOKED_STATUS_CESSATIONOFOPERATION);
+-    DefOCSPConst(REVOKED_STATUS_CERTIFICATEHOLD);
+-    DefOCSPConst(REVOKED_STATUS_REMOVEFROMCRL);
+-
+-    DefOCSPConst(NOCERTS);
+-    DefOCSPConst(NOINTERN);
+-    DefOCSPConst(NOSIGS);
+-    DefOCSPConst(NOCHAIN);
+-    DefOCSPConst(NOVERIFY);
+-    DefOCSPConst(NOEXPLICIT);
+-    DefOCSPConst(NOCASIGN);
+-    DefOCSPConst(NODELEGATED);
+-    DefOCSPConst(NOCHECKS);
+-    DefOCSPConst(TRUSTOTHER);
+-    DefOCSPConst(RESPID_KEY);
+-    DefOCSPConst(NOTIME);
+-
+-#define DefOCSPVConst(x) rb_define_const(mOCSP, "V_" #x, INT2NUM(V_OCSP_##x))
+-
+-    DefOCSPVConst(CERTSTATUS_GOOD);
+-    DefOCSPVConst(CERTSTATUS_REVOKED);
+-    DefOCSPVConst(CERTSTATUS_UNKNOWN);
+-    DefOCSPVConst(RESPID_NAME);
+-    DefOCSPVConst(RESPID_KEY);
++    /* Internal error in issuer */
++    rb_define_const(mOCSP, "RESPONSE_STATUS_INTERNALERROR", INT2NUM(OCSP_RESPONSE_STATUS_INTERNALERROR));
++
++    /* Illegal confirmation request */
++    rb_define_const(mOCSP, "RESPONSE_STATUS_MALFORMEDREQUEST", INT2NUM(OCSP_RESPONSE_STATUS_MALFORMEDREQUEST));
++
++    /* The certificate was revoked for an unknown reason */
++    rb_define_const(mOCSP, "REVOKED_STATUS_NOSTATUS", INT2NUM(OCSP_REVOKED_STATUS_NOSTATUS));
++
++    /* You must sign the request and resubmit */
++    rb_define_const(mOCSP, "RESPONSE_STATUS_SIGREQUIRED", INT2NUM(OCSP_RESPONSE_STATUS_SIGREQUIRED));
++
++    /* Response has valid confirmations */
++    rb_define_const(mOCSP, "RESPONSE_STATUS_SUCCESSFUL", INT2NUM(OCSP_RESPONSE_STATUS_SUCCESSFUL));
++
++    /* Try again later */
++    rb_define_const(mOCSP, "RESPONSE_STATUS_TRYLATER", INT2NUM(OCSP_RESPONSE_STATUS_TRYLATER));
++
++    /* The certificate subject's name or other information changed */
++    rb_define_const(mOCSP, "REVOKED_STATUS_AFFILIATIONCHANGED", INT2NUM(OCSP_REVOKED_STATUS_AFFILIATIONCHANGED));
++
++    /* This CA certificate was revoked due to a key compromise */
++    rb_define_const(mOCSP, "REVOKED_STATUS_CACOMPROMISE", INT2NUM(OCSP_REVOKED_STATUS_CACOMPROMISE));
++
++    /* The certificate is on hold */
++    rb_define_const(mOCSP, "REVOKED_STATUS_CERTIFICATEHOLD", INT2NUM(OCSP_REVOKED_STATUS_CERTIFICATEHOLD));
++
++    /* The certificate is no longer needed */
++    rb_define_const(mOCSP, "REVOKED_STATUS_CESSATIONOFOPERATION", INT2NUM(OCSP_REVOKED_STATUS_CESSATIONOFOPERATION));
++
++    /* The certificate was revoked due to a key compromise */
++    rb_define_const(mOCSP, "REVOKED_STATUS_KEYCOMPROMISE", INT2NUM(OCSP_REVOKED_STATUS_KEYCOMPROMISE));
++
++    /* The certificate was previously on hold and should now be removed from
++     * the CRL */
++    rb_define_const(mOCSP, "REVOKED_STATUS_REMOVEFROMCRL", INT2NUM(OCSP_REVOKED_STATUS_REMOVEFROMCRL));
++
++    /* The certificate was superseded by a new certificate */
++    rb_define_const(mOCSP, "REVOKED_STATUS_SUPERSEDED", INT2NUM(OCSP_REVOKED_STATUS_SUPERSEDED));
++
++    /* Your request is unauthorized. */
++    rb_define_const(mOCSP, "RESPONSE_STATUS_UNAUTHORIZED", INT2NUM(OCSP_RESPONSE_STATUS_UNAUTHORIZED));
++
++    /* The certificate was revoked for an unspecified reason */
++    rb_define_const(mOCSP, "REVOKED_STATUS_UNSPECIFIED", INT2NUM(OCSP_REVOKED_STATUS_UNSPECIFIED));
++
++    /* Do not include certificates in the response */
++    rb_define_const(mOCSP, "NOCERTS", INT2NUM(OCSP_NOCERTS));
++
++    /* Do not search certificates contained in the response for a signer */
++    rb_define_const(mOCSP, "NOINTERN", INT2NUM(OCSP_NOINTERN));
++
++    /* Do not check the signature on the response */
++    rb_define_const(mOCSP, "NOSIGS", INT2NUM(OCSP_NOSIGS));
++
++    /* Do not verify the certificate chain on the response */
++    rb_define_const(mOCSP, "NOCHAIN", INT2NUM(OCSP_NOCHAIN));
++
++    /* Do not verify the response at all */
++    rb_define_const(mOCSP, "NOVERIFY", INT2NUM(OCSP_NOVERIFY));
++
++    /* Do not check trust */
++    rb_define_const(mOCSP, "NOEXPLICIT", INT2NUM(OCSP_NOEXPLICIT));
++
++    /* (This flag is not used by OpenSSL 1.0.1g) */
++    rb_define_const(mOCSP, "NOCASIGN", INT2NUM(OCSP_NOCASIGN));
++
++    /* (This flag is not used by OpenSSL 1.0.1g) */
++    rb_define_const(mOCSP, "NODELEGATED", INT2NUM(OCSP_NODELEGATED));
++
++    /* Do not make additional signing certificate checks */
++    rb_define_const(mOCSP, "NOCHECKS", INT2NUM(OCSP_NOCHECKS));
++
++    /* Do not verify additional certificates */
++    rb_define_const(mOCSP, "TRUSTOTHER", INT2NUM(OCSP_TRUSTOTHER));
++
++    /* Identify the response by signing the certificate key ID */
++    rb_define_const(mOCSP, "RESPID_KEY", INT2NUM(OCSP_RESPID_KEY));
++
++    /* Do not include producedAt time in response */
++    rb_define_const(mOCSP, "NOTIME", INT2NUM(OCSP_NOTIME));
++
++    /* Indicates the certificate is not revoked but does not necessarily mean
++     * the certificate was issued or that this response is within the
++     * certificate's validity interval */
++    rb_define_const(mOCSP, "V_CERTSTATUS_GOOD", INT2NUM(V_OCSP_CERTSTATUS_GOOD));
++    /* Indicates the certificate has been revoked either permanently or
++     * temporarily (on hold). */
++    rb_define_const(mOCSP, "V_CERTSTATUS_REVOKED", INT2NUM(V_OCSP_CERTSTATUS_REVOKED));
++
++    /* Indicates the responder does not know about the certificate being
++     * requested. */
++    rb_define_const(mOCSP, "V_CERTSTATUS_UNKNOWN", INT2NUM(V_OCSP_CERTSTATUS_UNKNOWN));
++
++    /* The responder ID is based on the key name. */
++    rb_define_const(mOCSP, "V_RESPID_NAME", INT2NUM(V_OCSP_RESPID_NAME));
++
++    /* The responder ID is based on the public key. */
++    rb_define_const(mOCSP, "V_RESPID_KEY", INT2NUM(V_OCSP_RESPID_KEY));
+ }
+ 
+ #else /* ! OSSL_OCSP_ENABLED */
+ void
+-Init_ossl_ocsp()
++Init_ossl_ocsp(void)
+ {
+ }
+ #endif
+diff --git a/ext/openssl_cms/ossl_pkcs12.c b/ext/openssl_cms/ossl_pkcs12.c
+index 8a5f816..53e0e61 100644
+--- a/ext/openssl_cms/ossl_pkcs12.c
++++ b/ext/openssl_cms/ossl_pkcs12.c
+@@ -7,11 +7,11 @@
+ 
+ #define WrapPKCS12(klass, obj, p12) do { \
+     if(!(p12)) ossl_raise(rb_eRuntimeError, "PKCS12 wasn't initialized."); \
+-    (obj) = Data_Wrap_Struct((klass), 0, PKCS12_free, (p12)); \
++    (obj) = TypedData_Wrap_Struct((klass), &ossl_pkcs12_type, (p12)); \
+ } while (0)
+ 
+ #define GetPKCS12(obj, p12) do { \
+-    Data_Get_Struct((obj), PKCS12, (p12)); \
++    TypedData_Get_Struct((obj), PKCS12, &ossl_pkcs12_type, (p12)); \
+     if(!(p12)) ossl_raise(rb_eRuntimeError, "PKCS12 wasn't initialized."); \
+ } while (0)
+ 
+@@ -36,6 +36,20 @@ VALUE ePKCS12Error;
+ /*
+  * Private
+  */
++static void
++ossl_pkcs12_free(void *ptr)
++{
++    PKCS12_free(ptr);
++}
++
++static const rb_data_type_t ossl_pkcs12_type = {
++    "OpenSSL/PKCS12",
++    {
++	0, ossl_pkcs12_free,
++    },
++    0, 0, RUBY_TYPED_FREE_IMMEDIATELY,
++};
++
+ static VALUE
+ ossl_pkcs12_s_allocate(VALUE klass)
+ {
+@@ -192,7 +206,7 @@ ossl_pkcs12_to_der(VALUE self)
+ }
+ 
+ void
+-Init_ossl_pkcs12()
++Init_ossl_pkcs12(void)
+ {
+     /*
+      * Defines a file format commonly used to store private keys with
+diff --git a/ext/openssl_cms/ossl_pkcs5.c b/ext/openssl_cms/ossl_pkcs5.c
+index 3b615e4..6c7738a 100644
+--- a/ext/openssl_cms/ossl_pkcs5.c
++++ b/ext/openssl_cms/ossl_pkcs5.c
+@@ -87,7 +87,7 @@ ossl_pkcs5_pbkdf2_hmac_sha1(VALUE self, VALUE pass, VALUE salt, VALUE iter, VALU
+ #endif
+ 
+ void
+-Init_ossl_pkcs5()
++Init_ossl_pkcs5(void)
+ {
+     /*
+      * Password-based Encryption
+diff --git a/ext/openssl_cms/ossl_pkcs7.c b/ext/openssl_cms/ossl_pkcs7.c
+index 553a580..f4a5088 100644
+--- a/ext/openssl_cms/ossl_pkcs7.c
++++ b/ext/openssl_cms/ossl_pkcs7.c
+@@ -14,10 +14,10 @@
+     if (!(pkcs7)) { \
+ 	ossl_raise(rb_eRuntimeError, "PKCS7 wasn't initialized."); \
+     } \
+-    (obj) = Data_Wrap_Struct((klass), 0, PKCS7_free, (pkcs7)); \
++    (obj) = TypedData_Wrap_Struct((klass), &ossl_pkcs7_type, (pkcs7)); \
+ } while (0)
+ #define GetPKCS7(obj, pkcs7) do { \
+-    Data_Get_Struct((obj), PKCS7, (pkcs7)); \
++    TypedData_Get_Struct((obj), PKCS7, &ossl_pkcs7_type, (pkcs7)); \
+     if (!(pkcs7)) { \
+ 	ossl_raise(rb_eRuntimeError, "PKCS7 wasn't initialized."); \
+     } \
+@@ -31,10 +31,10 @@
+     if (!(p7si)) { \
+ 	ossl_raise(rb_eRuntimeError, "PKCS7si wasn't initialized."); \
+     } \
+-    (obj) = Data_Wrap_Struct((klass), 0, PKCS7_SIGNER_INFO_free, (p7si)); \
++    (obj) = TypedData_Wrap_Struct((klass), &ossl_pkcs7_signer_info_type, (p7si)); \
+ } while (0)
+ #define GetPKCS7si(obj, p7si) do { \
+-    Data_Get_Struct((obj), PKCS7_SIGNER_INFO, (p7si)); \
++    TypedData_Get_Struct((obj), PKCS7_SIGNER_INFO, &ossl_pkcs7_signer_info_type, (p7si)); \
+     if (!(p7si)) { \
+ 	ossl_raise(rb_eRuntimeError, "PKCS7si wasn't initialized."); \
+     } \
+@@ -48,10 +48,10 @@
+     if (!(p7ri)) { \
+ 	ossl_raise(rb_eRuntimeError, "PKCS7ri wasn't initialized."); \
+     } \
+-    (obj) = Data_Wrap_Struct((klass), 0, PKCS7_RECIP_INFO_free, (p7ri)); \
++    (obj) = TypedData_Wrap_Struct((klass), &ossl_pkcs7_recip_info_type, (p7ri)); \
+ } while (0)
+ #define GetPKCS7ri(obj, p7ri) do { \
+-    Data_Get_Struct((obj), PKCS7_RECIP_INFO, (p7ri)); \
++    TypedData_Get_Struct((obj), PKCS7_RECIP_INFO, &ossl_pkcs7_recip_info_type, (p7ri)); \
+     if (!(p7ri)) { \
+ 	ossl_raise(rb_eRuntimeError, "PKCS7ri wasn't initialized."); \
+     } \
+@@ -76,6 +76,48 @@ VALUE cPKCS7Signer;
+ VALUE cPKCS7Recipient;
+ VALUE ePKCS7Error;
+ 
++static void
++ossl_pkcs7_free(void *ptr)
++{
++    PKCS7_free(ptr);
++}
++
++static const rb_data_type_t ossl_pkcs7_type = {
++    "OpenSSL/PKCS7",
++    {
++	0, ossl_pkcs7_free,
++    },
++    0, 0, RUBY_TYPED_FREE_IMMEDIATELY,
++};
++
++static void
++ossl_pkcs7_signer_info_free(void *ptr)
++{
++    PKCS7_SIGNER_INFO_free(ptr);
++}
++
++static const rb_data_type_t ossl_pkcs7_signer_info_type = {
++    "OpenSSL/PKCS7/SIGNER_INFO",
++    {
++	0, ossl_pkcs7_signer_info_free,
++    },
++    0, 0, RUBY_TYPED_FREE_IMMEDIATELY,
++};
++
++static void
++ossl_pkcs7_recip_info_free(void *ptr)
++{
++    PKCS7_RECIP_INFO_free(ptr);
++}
++
++static const rb_data_type_t ossl_pkcs7_recip_info_type = {
++    "OpenSSL/PKCS7/RECIP_INFO",
++    {
++	0, ossl_pkcs7_recip_info_free,
++    },
++    0, 0, RUBY_TYPED_FREE_IMMEDIATELY,
++};
++
+ /*
+  * Public
+  * (MADE PRIVATE UNTIL SOMEBODY WILL NEED THEM)
+@@ -362,9 +404,10 @@ ossl_pkcs7_sym2typeid(VALUE sym)
+ {
+     int i, ret = Qnil;
+     const char *s;
++    size_t l;
+ 
+-    static struct {
+-        const char *name;
++    static const struct {
++        char name[20];
+         int nid;
+     } p7_type_tab[] = {
+         { "signed",             NID_pkcs7_signed },
+@@ -373,14 +416,15 @@ ossl_pkcs7_sym2typeid(VALUE sym)
+         { "enveloped",          NID_pkcs7_enveloped },
+         { "encrypted",          NID_pkcs7_encrypted },
+         { "digest",             NID_pkcs7_digest },
+-        { NULL,                 0 },
+     };
+ 
+-    if(TYPE(sym) == T_SYMBOL) s = rb_id2name(SYM2ID(sym));
+-    else s = StringValuePtr(sym);
+-    for(i = 0; i < numberof(p7_type_tab); i++){
+-	if(p7_type_tab[i].name == NULL)
++    if (RB_TYPE_P(sym, T_SYMBOL)) sym = rb_sym2str(sym);
++    else StringValue(sym);
++    RSTRING_GETMEM(sym, s, l);
++    for(i = 0; ; i++){
++	if(i == numberof(p7_type_tab))
+ 	    ossl_raise(ePKCS7Error, "unknown type \"%s\"", s);
++	if(strlen(p7_type_tab[i].name) != l) continue;
+ 	if(strcmp(p7_type_tab[i].name, s) == 0){
+ 	    ret = p7_type_tab[i].nid;
+ 	    break;
+@@ -978,7 +1022,7 @@ ossl_pkcs7ri_get_enc_key(VALUE self)
+  * INIT
+  */
+ void
+-Init_ossl_pkcs7()
++Init_ossl_pkcs7(void)
+ {
+     cPKCS7 = rb_define_class_under(mOSSL, "PKCS7", rb_cObject);
+     ePKCS7Error = rb_define_class_under(cPKCS7, "PKCS7Error", eOSSLError);
+diff --git a/ext/openssl_cms/ossl_pkey.c b/ext/openssl_cms/ossl_pkey.c
+index 878b221..aa9b046 100644
+--- a/ext/openssl_cms/ossl_pkey.c
++++ b/ext/openssl_cms/ossl_pkey.c
+@@ -69,9 +69,23 @@ ossl_generate_cb_stop(void *ptr)
+ }
+ #endif
+ 
++static void
++ossl_evp_pkey_free(void *ptr)
++{
++    EVP_PKEY_free(ptr);
++}
++
+ /*
+  * Public
+  */
++const rb_data_type_t ossl_evp_pkey_type = {
++    "OpenSSL/EVP_PKEY",
++    {
++	0, ossl_evp_pkey_free,
++    },
++    0, 0, RUBY_TYPED_FREE_IMMEDIATELY,
++};
++
+ VALUE
+ ossl_pkey_new(EVP_PKEY *pkey)
+ {
+@@ -342,7 +356,7 @@ ossl_pkey_verify(VALUE self, VALUE digest, VALUE sig, VALUE data)
+  * INIT
+  */
+ void
+-Init_ossl_pkey()
++Init_ossl_pkey(void)
+ {
+ #if 0
+     mOSSL = rb_define_module("OpenSSL"); /* let rdoc know about mOSSL */
+diff --git a/ext/openssl_cms/ossl_pkey.h b/ext/openssl_cms/ossl_pkey.h
+index 686e956..6c0b7fd 100644
+--- a/ext/openssl_cms/ossl_pkey.h
++++ b/ext/openssl_cms/ossl_pkey.h
+@@ -15,6 +15,7 @@ extern VALUE mPKey;
+ extern VALUE cPKey;
+ extern VALUE ePKeyError;
+ extern ID id_private_q;
++extern const rb_data_type_t ossl_evp_pkey_type;
+ 
+ #define OSSL_PKEY_SET_PRIVATE(obj) rb_iv_set((obj), "private", Qtrue)
+ #define OSSL_PKEY_SET_PUBLIC(obj)  rb_iv_set((obj), "private", Qfalse)
+@@ -24,11 +25,11 @@ extern ID id_private_q;
+     if (!(pkey)) { \
+ 	rb_raise(rb_eRuntimeError, "PKEY wasn't initialized!"); \
+     } \
+-    (obj) = Data_Wrap_Struct((klass), 0, EVP_PKEY_free, (pkey)); \
++    (obj) = TypedData_Wrap_Struct((klass), &ossl_evp_pkey_type, (pkey)); \
+     OSSL_PKEY_SET_PUBLIC(obj); \
+ } while (0)
+ #define GetPKey(obj, pkey) do {\
+-    Data_Get_Struct((obj), EVP_PKEY, (pkey));\
++    TypedData_Get_Struct((obj), EVP_PKEY, &ossl_evp_pkey_type, (pkey)); \
+     if (!(pkey)) { \
+ 	rb_raise(rb_eRuntimeError, "PKEY wasn't initialized!");\
+     } \
+diff --git a/ext/openssl_cms/ossl_pkey_dh.c b/ext/openssl_cms/ossl_pkey_dh.c
+index 011b6f0..cf28326 100644
+--- a/ext/openssl_cms/ossl_pkey_dh.c
++++ b/ext/openssl_cms/ossl_pkey_dh.c
+@@ -588,7 +588,7 @@ ossl_create_dh(unsigned char *p, size_t plen, unsigned char *g, size_t glen)
+  * INIT
+  */
+ void
+-Init_ossl_dh()
++Init_ossl_dh(void)
+ {
+ #if 0
+     mOSSL = rb_define_module("OpenSSL"); /* let rdoc know about mOSSL and mPKey */
+@@ -660,7 +660,7 @@ Init_ossl_dh()
+ 
+ #else /* defined NO_DH */
+ void
+-Init_ossl_dh()
++Init_ossl_dh(void)
+ {
+ }
+ #endif /* NO_DH */
+diff --git a/ext/openssl_cms/ossl_pkey_dsa.c b/ext/openssl_cms/ossl_pkey_dsa.c
+index 823b9b6..979ae15 100644
+--- a/ext/openssl_cms/ossl_pkey_dsa.c
++++ b/ext/openssl_cms/ossl_pkey_dsa.c
+@@ -563,7 +563,7 @@ OSSL_PKEY_BN(dsa, priv_key)
+  * INIT
+  */
+ void
+-Init_ossl_dsa()
++Init_ossl_dsa(void)
+ {
+ #if 0
+     mOSSL = rb_define_module("OpenSSL"); /* let rdoc know about mOSSL and mPKey */
+@@ -617,7 +617,7 @@ Init_ossl_dsa()
+ 
+ #else /* defined NO_DSA */
+ void
+-Init_ossl_dsa()
++Init_ossl_dsa(void)
+ {
+ }
+ #endif /* NO_DSA */
+diff --git a/ext/openssl_cms/ossl_pkey_ec.c b/ext/openssl_cms/ossl_pkey_ec.c
+index 5e419bd..d63f757 100644
+--- a/ext/openssl_cms/ossl_pkey_ec.c
++++ b/ext/openssl_cms/ossl_pkey_ec.c
+@@ -20,6 +20,8 @@ typedef struct {
+ #define EXPORT_PEM 0
+ #define EXPORT_DER 1
+ 
++static const rb_data_type_t ossl_ec_group_type;
++static const rb_data_type_t ossl_ec_point_type;
+ 
+ #define GetPKeyEC(obj, pkey) do { \
+     GetPKey((obj), (pkey)); \
+@@ -30,7 +32,7 @@ typedef struct {
+ 
+ #define SafeGet_ec_group(obj, group) do { \
+     OSSL_Check_Kind((obj), cEC_GROUP); \
+-    Data_Get_Struct((obj), ossl_ec_group, (group)); \
++    TypedData_Get_Struct((obj), ossl_ec_group, &ossl_ec_group_type, (group)); \
+ } while(0)
+ 
+ #define Get_EC_KEY(obj, key) do { \
+@@ -52,7 +54,7 @@ typedef struct {
+ 
+ #define Get_EC_GROUP(obj, g) do { \
+     ossl_ec_group *ec_group; \
+-    Data_Get_Struct((obj), ossl_ec_group, ec_group); \
++    TypedData_Get_Struct((obj), ossl_ec_group, &ossl_ec_group_type, ec_group); \
+     if (ec_group == NULL) \
+         ossl_raise(eEC_GROUP, "missing ossl_ec_group structure"); \
+     (g) = ec_group->group; \
+@@ -71,7 +73,7 @@ typedef struct {
+ 
+ #define Get_EC_POINT(obj, p) do { \
+     ossl_ec_point *ec_point; \
+-    Data_Get_Struct((obj), ossl_ec_point, ec_point); \
++    TypedData_Get_Struct((obj), ossl_ec_point, &ossl_ec_point_type, ec_point); \
+     if (ec_point == NULL) \
+         ossl_raise(eEC_POINT, "missing ossl_ec_point structure"); \
+     (p) = ec_point->point; \
+@@ -369,7 +371,7 @@ static VALUE ossl_ec_point_dup(const EC_POINT *point, VALUE group_v)
+     ossl_ec_point *new_point;
+ 
+     obj = rb_obj_alloc(cEC_POINT);
+-    Data_Get_Struct(obj, ossl_ec_point, new_point);
++    TypedData_Get_Struct(obj, ossl_ec_point, &ossl_ec_point_type, new_point);
+ 
+     SafeRequire_EC_GROUP(group_v, group);
+ 
+@@ -707,19 +709,28 @@ static VALUE ossl_ec_key_dsa_verify_asn1(VALUE self, VALUE data, VALUE sig)
+     UNREACHABLE;
+ }
+ 
+-static void ossl_ec_group_free(ossl_ec_group *ec_group)
++static void ossl_ec_group_free(void *ptr)
+ {
++    ossl_ec_group *ec_group = ptr;
+     if (!ec_group->dont_free && ec_group->group)
+         EC_GROUP_clear_free(ec_group->group);
+     ruby_xfree(ec_group);
+ }
+ 
++static const rb_data_type_t ossl_ec_group_type = {
++    "OpenSSL/ec_group",
++    {
++	0, ossl_ec_group_free,
++    },
++    0, 0, RUBY_TYPED_FREE_IMMEDIATELY,
++};
++
+ static VALUE ossl_ec_group_alloc(VALUE klass)
+ {
+     ossl_ec_group *ec_group;
+     VALUE obj;
+ 
+-    obj = Data_Make_Struct(klass, ossl_ec_group, 0, ossl_ec_group_free, ec_group);
++    obj = TypedData_Make_Struct(klass, ossl_ec_group, &ossl_ec_group_type, ec_group);
+ 
+     return obj;
+ }
+@@ -746,7 +757,7 @@ static VALUE ossl_ec_group_initialize(int argc, VALUE *argv, VALUE self)
+     ossl_ec_group *ec_group;
+     EC_GROUP *group = NULL;
+ 
+-    Data_Get_Struct(self, ossl_ec_group, ec_group);
++    TypedData_Get_Struct(self, ossl_ec_group, &ossl_ec_group_type, ec_group);
+     if (ec_group->group != NULL)
+         ossl_raise(rb_eRuntimeError, "EC_GROUP is already initialized");
+ 
+@@ -1219,19 +1230,28 @@ static VALUE ossl_ec_group_to_text(VALUE self)
+ }
+ 
+ 
+-static void ossl_ec_point_free(ossl_ec_point *ec_point)
++static void ossl_ec_point_free(void *ptr)
+ {
++    ossl_ec_point *ec_point = ptr;
+     if (!ec_point->dont_free && ec_point->point)
+         EC_POINT_clear_free(ec_point->point);
+     ruby_xfree(ec_point);
+ }
+ 
++static const rb_data_type_t ossl_ec_point_type = {
++    "OpenSSL/ec_point",
++    {
++	0, ossl_ec_point_free,
++    },
++    0, 0, RUBY_TYPED_FREE_IMMEDIATELY,
++};
++
+ static VALUE ossl_ec_point_alloc(VALUE klass)
+ {
+     ossl_ec_point *ec_point;
+     VALUE obj;
+ 
+-    obj = Data_Make_Struct(klass, ossl_ec_point, 0, ossl_ec_point_free, ec_point);
++    obj = TypedData_Make_Struct(klass, ossl_ec_point, &ossl_ec_point_type, ec_point);
+ 
+     return obj;
+ }
+@@ -1252,7 +1272,7 @@ static VALUE ossl_ec_point_initialize(int argc, VALUE *argv, VALUE self)
+     VALUE group_v = Qnil;
+     const EC_GROUP *group = NULL;
+ 
+-    Data_Get_Struct(self, ossl_ec_point, ec_point);
++    TypedData_Get_Struct(self, ossl_ec_point, &ossl_ec_point_type, ec_point);
+     if (ec_point->point)
+         ossl_raise(eEC_POINT, "EC_POINT already initialized");
+ 
+@@ -1556,7 +1576,7 @@ static void no_copy(VALUE klass)
+     rb_undef_method(klass, "initialize_copy");
+ }
+ 
+-void Init_ossl_ec()
++void Init_ossl_ec(void)
+ {
+ #ifdef DONT_NEED_RDOC_WORKAROUND
+     mOSSL = rb_define_module("OpenSSL");
+@@ -1677,7 +1697,7 @@ void Init_ossl_ec()
+ }
+ 
+ #else /* defined NO_EC */
+-void Init_ossl_ec()
++void Init_ossl_ec(void)
+ {
+ }
+ #endif /* NO_EC */
+diff --git a/ext/openssl_cms/ossl_pkey_rsa.c b/ext/openssl_cms/ossl_pkey_rsa.c
+index 4c346a0..0fef10a 100644
+--- a/ext/openssl_cms/ossl_pkey_rsa.c
++++ b/ext/openssl_cms/ossl_pkey_rsa.c
+@@ -626,7 +626,7 @@ OSSL_PKEY_BN(rsa, iqmp)
+ #define DefRSAConst(x) rb_define_const(cRSA, #x,INT2FIX(RSA_##x))
+ 
+ void
+-Init_ossl_rsa()
++Init_ossl_rsa(void)
+ {
+ #if 0
+     mOSSL = rb_define_module("OpenSSL"); /* let rdoc know about mOSSL and mPKey */
+@@ -694,7 +694,7 @@ Init_ossl_rsa()
+ 
+ #else /* defined NO_RSA */
+ void
+-Init_ossl_rsa()
++Init_ossl_rsa(void)
+ {
+ }
+ #endif /* NO_RSA */
+diff --git a/ext/openssl_cms/ossl_rand.c b/ext/openssl_cms/ossl_rand.c
+index 270a4b7..29cbf8c 100644
+--- a/ext/openssl_cms/ossl_rand.c
++++ b/ext/openssl_cms/ossl_rand.c
+@@ -2,36 +2,22 @@
+  * $Id$
+  * 'OpenSSL for Ruby' project
+  * Copyright (C) 2001-2002  Michal Rokos <m.rokos at sh.cvut.cz>
++ *
+  * All rights reserved.
+- */
+-/*
++ *
+  * This program is licenced under the same licence as Ruby.
+  * (See the file 'LICENCE'.)
+  */
+ #include "ossl.h"
+ 
+-/*
+- * Classes
+- */
+ VALUE mRandom;
+ VALUE eRandomError;
+ 
+ /*
+- * Struct
+- */
+-
+-/*
+- * Public
+- */
+-
+-/*
+- * Private
+- */
+-
+-/*
+  *  call-seq:
+  *     seed(str) -> str
+  *
++ * ::seed is equivalent to ::add where +entropy+ is length of +str+.
+  */
+ static VALUE
+ ossl_rand_seed(VALUE self, VALUE str)
+@@ -46,6 +32,23 @@ ossl_rand_seed(VALUE self, VALUE str)
+  *  call-seq:
+  *     add(str, entropy) -> self
+  *
++ * Mixes the bytes from +str+ into the Pseudo Random Number Generator(PRNG)
++ * state.
++ *
++ * Thus, if the data from +str+ are unpredictable to an adversary, this
++ * increases the uncertainty about the state and makes the PRNG output less
++ * predictable.
++ *
++ * The +entropy+ argument is (the lower bound of) an estimate of how much
++ * randomness is contained in +str+, measured in bytes.
++ *
++ *  Example:
++ *
++ *    pid = $$
++ *    now = Time.now
++ *    ary = [now.to_i, now.nsec, 1000, pid]
++ *    OpenSSL::Random.add(ary.join("").to_s, 0.0)
++ *    OpenSSL::Random.seed(ary.join("").to_s)
+  */
+ static VALUE
+ ossl_rand_add(VALUE self, VALUE str, VALUE entropy)
+@@ -60,6 +63,7 @@ ossl_rand_add(VALUE self, VALUE str, VALUE entropy)
+  *  call-seq:
+  *     load_random_file(filename) -> true
+  *
++ * Reads bytes from +filename+ and adds them to the PRNG.
+  */
+ static VALUE
+ ossl_rand_load_file(VALUE self, VALUE filename)
+@@ -76,6 +80,9 @@ ossl_rand_load_file(VALUE self, VALUE filename)
+  *  call-seq:
+  *     write_random_file(filename) -> true
+  *
++ * Writes a number of random generated bytes (currently 1024) to +filename+
++ * which can be used to initialize the PRNG by calling ::load_random_file in a
++ * later session.
+  */
+ static VALUE
+ ossl_rand_write_file(VALUE self, VALUE filename)
+@@ -89,8 +96,15 @@ ossl_rand_write_file(VALUE self, VALUE filename)
+ 
+ /*
+  *  call-seq:
+- *     random_bytes(length) -> aString
++ *	random_bytes(length) -> string
++ *
++ * Generates +string+ with +length+ number of cryptographically strong
++ * pseudo-random bytes.
+  *
++ *  Example:
++ *
++ *    OpenSSL::Random.random_bytes(12)
++ *    => "..."
+  */
+ static VALUE
+ ossl_rand_bytes(VALUE self, VALUE len)
+@@ -108,8 +122,17 @@ ossl_rand_bytes(VALUE self, VALUE len)
+ 
+ /*
+  *  call-seq:
+- *     pseudo_bytes(length) -> aString
++ *	pseudo_bytes(length) -> string
++ *
++ * Generates +string+ with +length+ number of pseudo-random bytes.
++ *
++ * Pseudo-random byte sequences generated by ::pseudo_bytes will be unique if
++ * they are of sufficient length, but are not necessarily unpredictable.
+  *
++ *  Example:
++ *
++ *    OpenSSL::Random.pseudo_bytes(12)
++ *    => "..."
+  */
+ static VALUE
+ ossl_rand_pseudo_bytes(VALUE self, VALUE len)
+@@ -129,6 +152,7 @@ ossl_rand_pseudo_bytes(VALUE self, VALUE len)
+  *  call-seq:
+  *     egd(filename) -> true
+  *
++ * Same as ::egd_bytes but queries 255 bytes by default.
+  */
+ static VALUE
+ ossl_rand_egd(VALUE self, VALUE filename)
+@@ -145,6 +169,10 @@ ossl_rand_egd(VALUE self, VALUE filename)
+  *  call-seq:
+  *     egd_bytes(filename, length) -> true
+  *
++ * Queries the entropy gathering daemon EGD on socket path given by +filename+.
++ *
++ * Fetches +length+ number of bytes and uses ::add to seed the OpenSSL built-in
++ * PRNG.
+  */
+ static VALUE
+ ossl_rand_egd_bytes(VALUE self, VALUE filename, VALUE len)
+@@ -171,15 +199,11 @@ ossl_rand_status(VALUE self)
+     return RAND_status() ? Qtrue : Qfalse;
+ }
+ 
+-#define DEFMETH(class, name, func, argc) \
+-	rb_define_method((class), (name), (func), (argc)); \
+-	rb_define_singleton_method((class), (name), (func), (argc));
+-
+ /*
+  * INIT
+  */
+ void
+-Init_ossl_rand()
++Init_ossl_rand(void)
+ {
+ #if 0
+     mOSSL = rb_define_module("OpenSSL"); /* let rdoc know about mOSSL */
+@@ -189,14 +213,14 @@ Init_ossl_rand()
+ 
+     eRandomError = rb_define_class_under(mRandom, "RandomError", eOSSLError);
+ 
+-    DEFMETH(mRandom, "seed", ossl_rand_seed, 1);
+-    DEFMETH(mRandom, "random_add", ossl_rand_add, 2);
+-    DEFMETH(mRandom, "load_random_file", ossl_rand_load_file, 1);
+-    DEFMETH(mRandom, "write_random_file", ossl_rand_write_file, 1);
+-    DEFMETH(mRandom, "random_bytes", ossl_rand_bytes, 1);
+-    DEFMETH(mRandom, "pseudo_bytes", ossl_rand_pseudo_bytes, 1);
+-    DEFMETH(mRandom, "egd", ossl_rand_egd, 1);
+-    DEFMETH(mRandom, "egd_bytes", ossl_rand_egd_bytes, 2);
+-    DEFMETH(mRandom, "status?", ossl_rand_status, 0)
++    rb_define_module_function(mRandom, "seed", ossl_rand_seed, 1);
++    rb_define_module_function(mRandom, "random_add", ossl_rand_add, 2);
++    rb_define_module_function(mRandom, "load_random_file", ossl_rand_load_file, 1);
++    rb_define_module_function(mRandom, "write_random_file", ossl_rand_write_file, 1);
++    rb_define_module_function(mRandom, "random_bytes", ossl_rand_bytes, 1);
++    rb_define_module_function(mRandom, "pseudo_bytes", ossl_rand_pseudo_bytes, 1);
++    rb_define_module_function(mRandom, "egd", ossl_rand_egd, 1);
++    rb_define_module_function(mRandom, "egd_bytes", ossl_rand_egd_bytes, 2);
++    rb_define_module_function(mRandom, "status?", ossl_rand_status, 0);
+ }
+ 
+diff --git a/ext/openssl_cms/ossl_ssl.c b/ext/openssl_cms/ossl_ssl.c
+index 206470c..af93252 100644
+--- a/ext/openssl_cms/ossl_ssl.c
++++ b/ext/openssl_cms/ossl_ssl.c
+@@ -24,6 +24,10 @@
+ #  define TO_SOCKET(s) (s)
+ #endif
+ 
++#define GetSSLCTX(obj, ctx) do { \
++	TypedData_Get_Struct((obj), SSL_CTX, &ossl_sslctx_type, (ctx));	\
++} while (0)
++
+ VALUE mSSL;
+ VALUE eSSLError;
+ VALUE cSSLContext;
+@@ -108,7 +112,7 @@ static VALUE sym_exception;
+ /*
+  * SSLContext class
+  */
+-struct {
++static const struct {
+     const char *name;
+     SSL_METHOD *(*func)(void);
+ } ossl_ssl_method_tab[] = {
+@@ -150,13 +154,22 @@ int ossl_ssl_ex_client_cert_cb_idx;
+ int ossl_ssl_ex_tmp_dh_callback_idx;
+ 
+ static void
+-ossl_sslctx_free(SSL_CTX *ctx)
++ossl_sslctx_free(void *ptr)
+ {
++    SSL_CTX *ctx = ptr;
+     if(ctx && SSL_CTX_get_ex_data(ctx, ossl_ssl_ex_store_p)== (void*)1)
+ 	ctx->cert_store = NULL;
+     SSL_CTX_free(ctx);
+ }
+ 
++static const rb_data_type_t ossl_sslctx_type = {
++    "OpenSSL/SSL/CTX",
++    {
++	0, ossl_sslctx_free,
++    },
++    0, 0, RUBY_TYPED_FREE_IMMEDIATELY,
++};
++
+ static VALUE
+ ossl_sslctx_s_alloc(VALUE klass)
+ {
+@@ -172,7 +185,7 @@ ossl_sslctx_s_alloc(VALUE klass)
+         ossl_raise(eSSLError, "SSL_CTX_new");
+     }
+     SSL_CTX_set_mode(ctx, mode);
+-    return Data_Wrap_Struct(klass, 0, ossl_sslctx_free, ctx);
++    return TypedData_Wrap_Struct(klass, &ossl_sslctx_type, ctx);
+ }
+ 
+ /*
+@@ -190,7 +203,7 @@ ossl_sslctx_set_ssl_version(VALUE self, VALUE ssl_method)
+     int i;
+ 
+     SSL_CTX *ctx;
+-    if(TYPE(ssl_method) == T_SYMBOL)
++    if (RB_TYPE_P(ssl_method, T_SYMBOL))
+ 	s = rb_id2name(SYM2ID(ssl_method));
+     else
+ 	s =  StringValuePtr(ssl_method);
+@@ -203,7 +216,7 @@ ossl_sslctx_set_ssl_version(VALUE self, VALUE ssl_method)
+     if (!method) {
+         ossl_raise(rb_eArgError, "unknown SSL method `%s'.", s);
+     }
+-    Data_Get_Struct(self, SSL_CTX, ctx);
++    GetSSLCTX(self, ctx);
+     if (SSL_CTX_set_ssl_version(ctx, method) != 1) {
+         ossl_raise(eSSLError, "SSL_CTX_set_ssl_version");
+     }
+@@ -244,7 +257,7 @@ ossl_call_client_cert_cb(VALUE obj)
+     VALUE cb, ary, cert, key;
+     SSL *ssl;
+ 
+-    Data_Get_Struct(obj, SSL, ssl);
++    GetSSL(obj, ssl);
+     cb = (VALUE)SSL_get_ex_data(ssl, ossl_ssl_ex_client_cert_cb_idx);
+     if (NIL_P(cb)) return Qfalse;
+     ary = rb_funcall(cb, rb_intern("call"), 1, obj);
+@@ -280,7 +293,7 @@ ossl_call_tmp_dh_callback(VALUE *args)
+     VALUE cb, dh;
+     EVP_PKEY *pkey;
+ 
+-    Data_Get_Struct(args[0], SSL, ssl);
++    GetSSL(args[0], ssl);
+     cb = (VALUE)SSL_get_ex_data(ssl, ossl_ssl_ex_tmp_dh_callback_idx);
+     if (NIL_P(cb)) return Qfalse;
+     dh = rb_funcall(cb, rb_intern("call"), 3, args[0], args[1], args[2]);
+@@ -482,7 +495,7 @@ ossl_sslctx_add_extra_chain_cert_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, arg))
+     X509 *x509;
+     SSL_CTX *ctx;
+ 
+-    Data_Get_Struct(arg, SSL_CTX, ctx);
++    GetSSLCTX(arg, ctx);
+     x509 = DupX509CertPtr(i);
+     if(!SSL_CTX_add_extra_chain_cert(ctx, x509)){
+ 	ossl_raise(eSSLError, NULL);
+@@ -513,8 +526,8 @@ ossl_call_servername_cb(VALUE ary)
+         SSL_CTX *ctx2;
+ 
+         ossl_sslctx_setup(ret_obj);
+-        Data_Get_Struct(ssl_obj, SSL, ssl);
+-        Data_Get_Struct(ret_obj, SSL_CTX, ctx2);
++        GetSSL(ssl_obj, ssl);
++        GetSSLCTX(ret_obj, ctx2);
+         SSL_set_SSL_CTX(ssl, ctx2);
+     } else if (!NIL_P(ret_obj)) {
+             ossl_raise(rb_eArgError, "servername_cb must return an OpenSSL::SSL::SSLContext object or nil");
+@@ -665,7 +678,7 @@ ossl_sslctx_setup(VALUE self)
+     VALUE val;
+ 
+     if(OBJ_FROZEN(self)) return Qnil;
+-    Data_Get_Struct(self, SSL_CTX, ctx);
++    GetSSLCTX(self, ctx);
+ 
+ #if !defined(OPENSSL_NO_DH)
+     if (RTEST(ossl_sslctx_get_tmp_dh_cb(self))){
+@@ -716,7 +729,7 @@ ossl_sslctx_setup(VALUE self)
+ 
+     val = ossl_sslctx_get_client_ca(self);
+     if(!NIL_P(val)){
+-	if(TYPE(val) == T_ARRAY){
++	if (RB_TYPE_P(val, T_ARRAY)) {
+ 	    for(i = 0; i < RARRAY_LEN(val); i++){
+ 		client_ca = GetX509CertPtr(RARRAY_PTR(val)[i]);
+         	if (!SSL_CTX_add_client_CA(ctx, client_ca)){
+@@ -841,7 +854,7 @@ ossl_sslctx_get_ciphers(VALUE self)
+     VALUE ary;
+     int i, num;
+ 
+-    Data_Get_Struct(self, SSL_CTX, ctx);
++    GetSSLCTX(self, ctx);
+     if(!ctx){
+         rb_warning("SSL_CTX is not initialized.");
+         return Qnil;
+@@ -882,11 +895,11 @@ ossl_sslctx_set_ciphers(VALUE self, VALUE v)
+     rb_check_frozen(self);
+     if (NIL_P(v))
+ 	return v;
+-    else if (TYPE(v) == T_ARRAY) {
++    else if (RB_TYPE_P(v, T_ARRAY)) {
+         str = rb_str_new(0, 0);
+         for (i = 0; i < RARRAY_LEN(v); i++) {
+             elem = rb_ary_entry(v, i);
+-            if (TYPE(elem) == T_ARRAY) elem = rb_ary_entry(elem, 0);
++            if (RB_TYPE_P(elem, T_ARRAY)) elem = rb_ary_entry(elem, 0);
+             elem = rb_String(elem);
+             rb_str_append(str, elem);
+             if (i < RARRAY_LEN(v)-1) rb_str_cat2(str, ":");
+@@ -896,7 +909,7 @@ ossl_sslctx_set_ciphers(VALUE self, VALUE v)
+         StringValue(str);
+     }
+ 
+-    Data_Get_Struct(self, SSL_CTX, ctx);
++    GetSSLCTX(self, ctx);
+     if(!ctx){
+         ossl_raise(eSSLError, "SSL_CTX is not initialized.");
+         return Qnil;
+@@ -920,7 +933,7 @@ ossl_sslctx_session_add(VALUE self, VALUE arg)
+     SSL_CTX *ctx;
+     SSL_SESSION *sess;
+ 
+-    Data_Get_Struct(self, SSL_CTX, ctx);
++    GetSSLCTX(self, ctx);
+     SafeGetSSLSession(arg, sess);
+ 
+     return SSL_CTX_add_session(ctx, sess) == 1 ? Qtrue : Qfalse;
+@@ -938,7 +951,7 @@ ossl_sslctx_session_remove(VALUE self, VALUE arg)
+     SSL_CTX *ctx;
+     SSL_SESSION *sess;
+ 
+-    Data_Get_Struct(self, SSL_CTX, ctx);
++    GetSSLCTX(self, ctx);
+     SafeGetSSLSession(arg, sess);
+ 
+     return SSL_CTX_remove_session(ctx, sess) == 1 ? Qtrue : Qfalse;
+@@ -955,7 +968,7 @@ ossl_sslctx_get_session_cache_mode(VALUE self)
+ {
+     SSL_CTX *ctx;
+ 
+-    Data_Get_Struct(self, SSL_CTX, ctx);
++    GetSSLCTX(self, ctx);
+ 
+     return LONG2NUM(SSL_CTX_get_session_cache_mode(ctx));
+ }
+@@ -973,7 +986,7 @@ ossl_sslctx_set_session_cache_mode(VALUE self, VALUE arg)
+ {
+     SSL_CTX *ctx;
+ 
+-    Data_Get_Struct(self, SSL_CTX, ctx);
++    GetSSLCTX(self, ctx);
+ 
+     SSL_CTX_set_session_cache_mode(ctx, NUM2LONG(arg));
+ 
+@@ -992,7 +1005,7 @@ ossl_sslctx_get_session_cache_size(VALUE self)
+ {
+     SSL_CTX *ctx;
+ 
+-    Data_Get_Struct(self, SSL_CTX, ctx);
++    GetSSLCTX(self, ctx);
+ 
+     return LONG2NUM(SSL_CTX_sess_get_cache_size(ctx));
+ }
+@@ -1009,7 +1022,7 @@ ossl_sslctx_set_session_cache_size(VALUE self, VALUE arg)
+ {
+     SSL_CTX *ctx;
+ 
+-    Data_Get_Struct(self, SSL_CTX, ctx);
++    GetSSLCTX(self, ctx);
+ 
+     SSL_CTX_sess_set_cache_size(ctx, NUM2LONG(arg));
+ 
+@@ -1044,7 +1057,7 @@ ossl_sslctx_get_session_cache_stats(VALUE self)
+     SSL_CTX *ctx;
+     VALUE hash;
+ 
+-    Data_Get_Struct(self, SSL_CTX, ctx);
++    GetSSLCTX(self, ctx);
+ 
+     hash = rb_hash_new();
+     rb_hash_aset(hash, ID2SYM(rb_intern("cache_num")), LONG2NUM(SSL_CTX_sess_number(ctx)));
+@@ -1079,7 +1092,7 @@ ossl_sslctx_flush_sessions(int argc, VALUE *argv, VALUE self)
+ 
+     rb_scan_args(argc, argv, "01", &arg1);
+ 
+-    Data_Get_Struct(self, SSL_CTX, ctx);
++    GetSSLCTX(self, ctx);
+ 
+     if (NIL_P(arg1)) {
+         tm = time(0);
+@@ -1120,15 +1133,23 @@ ossl_ssl_shutdown(SSL *ssl)
+ }
+ 
+ static void
+-ossl_ssl_free(SSL *ssl)
++ossl_ssl_free(void *ssl)
+ {
+     SSL_free(ssl);
+ }
+ 
++const rb_data_type_t ossl_ssl_type = {
++    "OpenSSL/SSL",
++    {
++	0, ossl_ssl_free,
++    },
++    0, 0, RUBY_TYPED_FREE_IMMEDIATELY,
++};
++
+ static VALUE
+ ossl_ssl_s_alloc(VALUE klass)
+ {
+-    return Data_Wrap_Struct(klass, 0, ossl_ssl_free, NULL);
++    return TypedData_Wrap_Struct(klass, &ossl_ssl_type, NULL);
+ }
+ 
+ /*
+@@ -1177,14 +1198,14 @@ ossl_ssl_setup(VALUE self)
+     SSL *ssl;
+     rb_io_t *fptr;
+ 
+-    Data_Get_Struct(self, SSL, ssl);
++    GetSSL(self, ssl);
+     if(!ssl){
+ #ifdef HAVE_SSL_SET_TLSEXT_HOST_NAME
+ 	VALUE hostname = rb_iv_get(self, "@hostname");
+ #endif
+ 
+         v_ctx = ossl_ssl_get_ctx(self);
+-        Data_Get_Struct(v_ctx, SSL_CTX, ctx);
++        GetSSLCTX(v_ctx, ctx);
+ 
+         ssl = SSL_new(ctx);
+         if (!ssl) {
+@@ -1224,7 +1245,7 @@ ossl_ssl_setup(VALUE self)
+ 
+ #define ossl_ssl_data_get_struct(v, ssl)		\
+ do {							\
+-    Data_Get_Struct((v), SSL, (ssl));			\
++    GetSSL((v), (ssl)); 				\
+     if (!(ssl)) {					\
+         rb_warning("SSL session is not started yet.");  \
+         return Qnil;					\
+@@ -1394,7 +1415,7 @@ ossl_ssl_read_internal(int argc, VALUE *argv, VALUE self, int nonblock)
+     }
+     if(ilen == 0) return str;
+ 
+-    Data_Get_Struct(self, SSL, ssl);
++    GetSSL(self, ssl);
+     GetOpenFile(ossl_ssl_get_io(self), fptr);
+     if (ssl) {
+ 	if(!nonblock && SSL_pending(ssl) <= 0)
+@@ -1431,7 +1452,11 @@ ossl_ssl_read_internal(int argc, VALUE *argv, VALUE self, int nonblock)
+     else {
+         ID meth = nonblock ? rb_intern("read_nonblock") : rb_intern("sysread");
+         rb_warning("SSL session is not started yet.");
+-        return rb_funcall(ossl_ssl_get_io(self), meth, 2, len, str);
++        if (nonblock) {
++          return rb_funcall(ossl_ssl_get_io(self), meth, 3, len, str, opts);
++        } else {
++          return rb_funcall(ossl_ssl_get_io(self), meth, 2, len, str);
++        }
+     }
+ 
+   end:
+@@ -1482,7 +1507,7 @@ ossl_ssl_write_internal(VALUE self, VALUE str, int nonblock, int no_exception)
+     rb_io_t *fptr;
+ 
+     StringValue(str);
+-    Data_Get_Struct(self, SSL, ssl);
++    GetSSL(self, ssl);
+     GetOpenFile(ossl_ssl_get_io(self), fptr);
+ 
+     if (ssl) {
+@@ -1562,18 +1587,22 @@ static VALUE
+ ossl_ssl_close(VALUE self)
+ {
+     SSL *ssl;
++    VALUE io;
+ 
+-    ossl_ssl_data_get_struct(self, ssl);
++    /* ossl_ssl_data_get_struct() is not usable here because it may return
++     * from this function; */
+ 
+-    if (ssl) {
+-	VALUE io = ossl_ssl_get_io(self);
+-	if (!RTEST(rb_funcall(io, rb_intern("closed?"), 0))) {
+-	    ossl_ssl_shutdown(ssl);
+-	    SSL_free(ssl);
+-	    DATA_PTR(self) = NULL;
+-	    if (RTEST(ossl_ssl_get_sync_close(self)))
+-		rb_funcall(io, rb_intern("close"), 0);
+-	}
++    GetSSL(self, ssl);
++
++    io = ossl_ssl_get_io(self);
++    if (!RTEST(rb_funcall(io, rb_intern("closed?"), 0))) {
++        if (ssl) {
++            ossl_ssl_shutdown(ssl);
++            SSL_free(ssl);
++        }
++        DATA_PTR(self) = NULL;
++        if (RTEST(ossl_ssl_get_sync_close(self)))
++            rb_funcall(io, rb_intern("close"), 0);
+     }
+ 
+     return Qnil;
+@@ -1850,7 +1879,7 @@ ossl_ssl_npn_protocol(VALUE self)
+ #endif /* !defined(OPENSSL_NO_SOCK) */
+ 
+ void
+-Init_ossl_ssl()
++Init_ossl_ssl(void)
+ {
+     int i;
+     VALUE ary;
+@@ -2019,7 +2048,7 @@ Init_ossl_ssl()
+     rb_attr(cSSLContext, rb_intern("session_get_cb"), 1, 1, Qfalse);
+ 
+     /*
+-     * A callback invoked when a new session was negotiatied.
++     * A callback invoked when a new session was negotiated.
+      *
+      * The callback is invoked with an SSLSocket.  If false is returned the
+      * session will be removed from the internal cache.
+diff --git a/ext/openssl_cms/ossl_ssl.h b/ext/openssl_cms/ossl_ssl.h
+index 034762f..0c20b10 100644
+--- a/ext/openssl_cms/ossl_ssl.h
++++ b/ext/openssl_cms/ossl_ssl.h
+@@ -11,8 +11,12 @@
+ #if !defined(_OSSL_SSL_H_)
+ #define _OSSL_SSL_H_
+ 
++#define GetSSL(obj, ssl) do { \
++	TypedData_Get_Struct((obj), SSL, &ossl_ssl_type, (ssl)); \
++} while (0)
++
+ #define GetSSLSession(obj, sess) do { \
+-	Data_Get_Struct((obj), SSL_SESSION, (sess)); \
++	TypedData_Get_Struct((obj), SSL_SESSION, &ossl_ssl_session_type, (sess)); \
+ 	if (!(sess)) { \
+ 		ossl_raise(rb_eRuntimeError, "SSL Session wasn't initialized."); \
+ 	} \
+@@ -23,6 +27,8 @@
+ 	GetSSLSession((obj), (sess)); \
+ } while (0)
+ 
++extern const rb_data_type_t ossl_ssl_type;
++extern const rb_data_type_t ossl_ssl_session_type;
+ extern VALUE mSSL;
+ extern VALUE eSSLError;
+ extern VALUE cSSLSocket;
+diff --git a/ext/openssl_cms/ossl_ssl_session.c b/ext/openssl_cms/ossl_ssl_session.c
+index a7437ca..5318f1a 100644
+--- a/ext/openssl_cms/ossl_ssl_session.c
++++ b/ext/openssl_cms/ossl_ssl_session.c
+@@ -4,25 +4,26 @@
+ 
+ #include "ossl.h"
+ 
+-#define GetSSLSession(obj, sess) do { \
+-	Data_Get_Struct((obj), SSL_SESSION, (sess)); \
+-	if (!(sess)) { \
+-		ossl_raise(rb_eRuntimeError, "SSL Session wasn't initialized."); \
+-	} \
+-} while (0)
+-
+-#define SafeGetSSLSession(obj, sess) do { \
+-	OSSL_Check_Kind((obj), cSSLSession); \
+-	GetSSLSession((obj), (sess)); \
+-} while (0)
+-
+-
+ VALUE cSSLSession;
+ static VALUE eSSLSession;
+ 
++static void
++ossl_ssl_session_free(void *ptr)
++{
++    SSL_SESSION_free(ptr);
++}
++
++const rb_data_type_t ossl_ssl_session_type = {
++    "OpenSSL/SSL/Session",
++    {
++	0, ossl_ssl_session_free,
++    },
++    0, 0, RUBY_TYPED_FREE_IMMEDIATELY,
++};
++
+ static VALUE ossl_ssl_session_alloc(VALUE klass)
+ {
+-	return Data_Wrap_Struct(klass, 0, SSL_SESSION_free, NULL);
++	return TypedData_Wrap_Struct(klass, &ossl_ssl_session_type, NULL);
+ }
+ 
+ /*
+@@ -43,7 +44,7 @@ static VALUE ossl_ssl_session_initialize(VALUE self, VALUE arg1)
+ 	if (rb_obj_is_instance_of(arg1, cSSLSocket)) {
+ 		SSL *ssl;
+ 
+-		Data_Get_Struct(arg1, SSL, ssl);
++		GetSSL(arg1, ssl);
+ 
+ 		if (!ssl || (ctx = SSL_get1_session(ssl)) == NULL)
+ 			ossl_raise(eSSLSession, "no session available");
+diff --git a/ext/openssl_cms/ossl_x509.c b/ext/openssl_cms/ossl_x509.c
+index fd1d9b6..4de4545 100644
+--- a/ext/openssl_cms/ossl_x509.c
++++ b/ext/openssl_cms/ossl_x509.c
+@@ -17,7 +17,7 @@ VALUE mX509;
+   rb_define_const(mX509, "DEFAULT_" #x, rb_str_new2(X509_get_default_##i()))
+ 
+ void
+-Init_ossl_x509()
++Init_ossl_x509(void)
+ {
+     mX509 = rb_define_module_under(mOSSL, "X509");
+ 
+diff --git a/ext/openssl_cms/ossl_x509attr.c b/ext/openssl_cms/ossl_x509attr.c
+index d50f88c..c9036ca 100644
+--- a/ext/openssl_cms/ossl_x509attr.c
++++ b/ext/openssl_cms/ossl_x509attr.c
+@@ -14,10 +14,10 @@
+     if (!(attr)) { \
+ 	ossl_raise(rb_eRuntimeError, "ATTR wasn't initialized!"); \
+     } \
+-    (obj) = Data_Wrap_Struct((klass), 0, X509_ATTRIBUTE_free, (attr)); \
++    (obj) = TypedData_Wrap_Struct((klass), &ossl_x509attr_type, (attr)); \
+ } while (0)
+ #define GetX509Attr(obj, attr) do { \
+-    Data_Get_Struct((obj), X509_ATTRIBUTE, (attr)); \
++    TypedData_Get_Struct((obj), X509_ATTRIBUTE, &ossl_x509attr_type, (attr)); \
+     if (!(attr)) { \
+ 	ossl_raise(rb_eRuntimeError, "ATTR wasn't initialized!"); \
+     } \
+@@ -33,6 +33,20 @@
+ VALUE cX509Attr;
+ VALUE eX509AttrError;
+ 
++static void
++ossl_x509attr_free(void *ptr)
++{
++    X509_ATTRIBUTE_free(ptr);
++}
++
++static const rb_data_type_t ossl_x509attr_type = {
++    "OpenSSL/X509/ATTRIBUTE",
++    {
++	0, ossl_x509attr_free,
++    },
++    0, 0, RUBY_TYPED_FREE_IMMEDIATELY,
++};
++
+ /*
+  * Public
+  */
+@@ -260,7 +274,7 @@ ossl_x509attr_to_der(VALUE self)
+  * X509_ATTRIBUTE init
+  */
+ void
+-Init_ossl_x509attr()
++Init_ossl_x509attr(void)
+ {
+     eX509AttrError = rb_define_class_under(mX509, "AttributeError", eOSSLError);
+ 
+diff --git a/ext/openssl_cms/ossl_x509cert.c b/ext/openssl_cms/ossl_x509cert.c
+index 84cedc7..b76ea79 100644
+--- a/ext/openssl_cms/ossl_x509cert.c
++++ b/ext/openssl_cms/ossl_x509cert.c
+@@ -14,10 +14,10 @@
+     if (!(x509)) { \
+ 	ossl_raise(rb_eRuntimeError, "CERT wasn't initialized!"); \
+     } \
+-    (obj) = Data_Wrap_Struct((klass), 0, X509_free, (x509)); \
++    (obj) = TypedData_Wrap_Struct((klass), &ossl_x509_type, (x509)); \
+ } while (0)
+ #define GetX509(obj, x509) do { \
+-    Data_Get_Struct((obj), X509, (x509)); \
++    TypedData_Get_Struct((obj), X509, &ossl_x509_type, (x509)); \
+     if (!(x509)) { \
+ 	ossl_raise(rb_eRuntimeError, "CERT wasn't initialized!"); \
+     } \
+@@ -33,6 +33,20 @@
+ VALUE cX509Cert;
+ VALUE eX509CertError;
+ 
++static void
++ossl_x509_free(void *ptr)
++{
++    X509_free(ptr);
++}
++
++static const rb_data_type_t ossl_x509_type = {
++    "OpenSSL/X509",
++    {
++	0, ossl_x509_free,
++    },
++    0, 0, RUBY_TYPED_FREE_IMMEDIATELY,
++};
++
+ /*
+  * Public
+  */
+@@ -693,42 +707,22 @@ ossl_x509_add_extension(VALUE self, VALUE extension)
+ static VALUE
+ ossl_x509_inspect(VALUE self)
+ {
+-    VALUE str;
+-    const char *cname = rb_class2name(rb_obj_class(self));
+-
+-    str = rb_str_new2("#<");
+-    rb_str_cat2(str, cname);
+-    rb_str_cat2(str, " ");
+-
+-    rb_str_cat2(str, "subject=");
+-    rb_str_append(str, rb_inspect(ossl_x509_get_subject(self)));
+-    rb_str_cat2(str, ", ");
+-
+-    rb_str_cat2(str, "issuer=");
+-    rb_str_append(str, rb_inspect(ossl_x509_get_issuer(self)));
+-    rb_str_cat2(str, ", ");
+-
+-    rb_str_cat2(str, "serial=");
+-    rb_str_append(str, rb_inspect(ossl_x509_get_serial(self)));
+-    rb_str_cat2(str, ", ");
+-
+-    rb_str_cat2(str, "not_before=");
+-    rb_str_append(str, rb_inspect(ossl_x509_get_not_before(self)));
+-    rb_str_cat2(str, ", ");
+-
+-    rb_str_cat2(str, "not_after=");
+-    rb_str_append(str, rb_inspect(ossl_x509_get_not_after(self)));
+-
+-    str = rb_str_cat2(str, ">");
+-
+-    return str;
++    return rb_sprintf("#<%"PRIsVALUE": subject=%+"PRIsVALUE", "
++		      "issuer=%+"PRIsVALUE", serial=%+"PRIsVALUE", "
++		      "not_before=%+"PRIsVALUE", not_after=%+"PRIsVALUE">",
++		      rb_obj_class(self),
++		      ossl_x509_get_subject(self),
++		      ossl_x509_get_issuer(self),
++		      ossl_x509_get_serial(self),
++		      ossl_x509_get_not_before(self),
++		      ossl_x509_get_not_after(self));
+ }
+ 
+ /*
+  * INIT
+  */
+ void
+-Init_ossl_x509cert()
++Init_ossl_x509cert(void)
+ {
+ 
+ #if 0
+diff --git a/ext/openssl_cms/ossl_x509crl.c b/ext/openssl_cms/ossl_x509crl.c
+index dec13c8..461c226 100644
+--- a/ext/openssl_cms/ossl_x509crl.c
++++ b/ext/openssl_cms/ossl_x509crl.c
+@@ -14,10 +14,10 @@
+     if (!(crl)) { \
+ 	ossl_raise(rb_eRuntimeError, "CRL wasn't initialized!"); \
+     } \
+-    (obj) = Data_Wrap_Struct((klass), 0, X509_CRL_free, (crl)); \
++    (obj) = TypedData_Wrap_Struct((klass), &ossl_x509crl_type, (crl)); \
+ } while (0)
+ #define GetX509CRL(obj, crl) do { \
+-    Data_Get_Struct((obj), X509_CRL, (crl)); \
++    TypedData_Get_Struct((obj), X509_CRL, &ossl_x509crl_type, (crl)); \
+     if (!(crl)) { \
+ 	ossl_raise(rb_eRuntimeError, "CRL wasn't initialized!"); \
+     } \
+@@ -33,6 +33,20 @@
+ VALUE cX509CRL;
+ VALUE eX509CRLError;
+ 
++static void
++ossl_x509crl_free(void *ptr)
++{
++    X509_CRL_free(ptr);
++}
++
++static const rb_data_type_t ossl_x509crl_type = {
++    "OpenSSL/X509/CRL",
++    {
++	0, ossl_x509crl_free,
++    },
++    0, 0, RUBY_TYPED_FREE_IMMEDIATELY,
++};
++
+ /*
+  * PUBLIC
+  */
+@@ -502,7 +516,7 @@ ossl_x509crl_add_extension(VALUE self, VALUE extension)
+  * INIT
+  */
+ void
+-Init_ossl_x509crl()
++Init_ossl_x509crl(void)
+ {
+     eX509CRLError = rb_define_class_under(mX509, "CRLError", eOSSLError);
+ 
+diff --git a/ext/openssl_cms/ossl_x509ext.c b/ext/openssl_cms/ossl_x509ext.c
+index bd2e1dd..faffe06 100644
+--- a/ext/openssl_cms/ossl_x509ext.c
++++ b/ext/openssl_cms/ossl_x509ext.c
+@@ -14,10 +14,10 @@
+     if (!(ext)) { \
+ 	ossl_raise(rb_eRuntimeError, "EXT wasn't initialized!"); \
+     } \
+-    (obj) = Data_Wrap_Struct((klass), 0, X509_EXTENSION_free, (ext)); \
++    (obj) = TypedData_Wrap_Struct((klass), &ossl_x509ext_type, (ext)); \
+ } while (0)
+ #define GetX509Ext(obj, ext) do { \
+-    Data_Get_Struct((obj), X509_EXTENSION, (ext)); \
++    TypedData_Get_Struct((obj), X509_EXTENSION, &ossl_x509ext_type, (ext)); \
+     if (!(ext)) { \
+ 	ossl_raise(rb_eRuntimeError, "EXT wasn't initialized!"); \
+     } \
+@@ -30,10 +30,10 @@
+     if (!((ctx) = OPENSSL_malloc(sizeof(X509V3_CTX)))) \
+         ossl_raise(rb_eRuntimeError, "CTX wasn't allocated!"); \
+     X509V3_set_ctx((ctx), NULL, NULL, NULL, NULL, 0); \
+-    (obj) = Data_Wrap_Struct((klass), 0, ossl_x509extfactory_free, (ctx)); \
++    (obj) = TypedData_Wrap_Struct((klass), &ossl_x509extfactory_type, (ctx)); \
+ } while (0)
+ #define GetX509ExtFactory(obj, ctx) do { \
+-    Data_Get_Struct((obj), X509V3_CTX, (ctx)); \
++    TypedData_Get_Struct((obj), X509V3_CTX, &ossl_x509extfactory_type, (ctx)); \
+     if (!(ctx)) { \
+ 	ossl_raise(rb_eRuntimeError, "CTX wasn't initialized!"); \
+     } \
+@@ -46,6 +46,20 @@ VALUE cX509Ext;
+ VALUE cX509ExtFactory;
+ VALUE eX509ExtError;
+ 
++static void
++ossl_x509ext_free(void *ptr)
++{
++    X509_EXTENSION_free(ptr);
++}
++
++static const rb_data_type_t ossl_x509ext_type = {
++    "OpenSSL/X509/EXTENSION",
++    {
++	0, ossl_x509ext_free,
++    },
++    0, 0, RUBY_TYPED_FREE_IMMEDIATELY,
++};
++
+ /*
+  * Public
+  */
+@@ -98,11 +112,19 @@ DupX509ExtPtr(VALUE obj)
+  * Ext factory
+  */
+ static void
+-ossl_x509extfactory_free(X509V3_CTX *ctx)
++ossl_x509extfactory_free(void *ctx)
+ {
+     OPENSSL_free(ctx);
+ }
+ 
++static const rb_data_type_t ossl_x509extfactory_type = {
++    "OpenSSL/X509/EXTENSION/Factory",
++    {
++	0, ossl_x509extfactory_free,
++    },
++    0, 0, RUBY_TYPED_FREE_IMMEDIATELY,
++};
++
+ static VALUE
+ ossl_x509extfactory_alloc(VALUE klass)
+ {
+@@ -436,7 +458,7 @@ ossl_x509ext_to_der(VALUE obj)
+  * INIT
+  */
+ void
+-Init_ossl_x509ext()
++Init_ossl_x509ext(void)
+ {
+     eX509ExtError = rb_define_class_under(mX509, "ExtensionError", eOSSLError);
+ 
+diff --git a/ext/openssl_cms/ossl_x509name.c b/ext/openssl_cms/ossl_x509name.c
+index 6de79d4..546cf3b 100644
+--- a/ext/openssl_cms/ossl_x509name.c
++++ b/ext/openssl_cms/ossl_x509name.c
+@@ -14,10 +14,10 @@
+     if (!(name)) { \
+ 	ossl_raise(rb_eRuntimeError, "Name wasn't initialized."); \
+     } \
+-    (obj) = Data_Wrap_Struct((klass), 0, X509_NAME_free, (name)); \
++    (obj) = TypedData_Wrap_Struct((klass), &ossl_x509name_type, (name)); \
+ } while (0)
+ #define GetX509Name(obj, name) do { \
+-    Data_Get_Struct((obj), X509_NAME, (name)); \
++    TypedData_Get_Struct((obj), X509_NAME, &ossl_x509name_type, (name)); \
+     if (!(name)) { \
+ 	ossl_raise(rb_eRuntimeError, "Name wasn't initialized."); \
+     } \
+@@ -38,6 +38,20 @@
+ VALUE cX509Name;
+ VALUE eX509NameError;
+ 
++static void
++ossl_x509name_free(void *ptr)
++{
++    X509_NAME_free(ptr);
++}
++
++static const rb_data_type_t ossl_x509name_type = {
++    "OpenSSL/X509/NAME",
++    {
++	0, ossl_x509name_free,
++    },
++    0, 0, RUBY_TYPED_FREE_IMMEDIATELY,
++};
++
+ /*
+  * Public
+  */
+@@ -183,13 +197,14 @@ VALUE ossl_x509name_add_entry(int argc, VALUE *argv, VALUE self)
+ {
+     X509_NAME *name;
+     VALUE oid, value, type;
++    const char *oid_name;
+ 
+     rb_scan_args(argc, argv, "21", &oid, &value, &type);
+-    StringValue(oid);
++    oid_name = StringValueCStr(oid);
+     StringValue(value);
+     if(NIL_P(type)) type = rb_aref(OBJECT_TYPE_TEMPLATE, oid);
+     GetX509Name(self, name);
+-    if (!X509_NAME_add_entry_by_txt(name, RSTRING_PTR(oid), NUM2INT(type),
++    if (!X509_NAME_add_entry_by_txt(name, oid_name, NUM2INT(type),
+ 		(const unsigned char *)RSTRING_PTR(value), RSTRING_LENINT(value), -1, 0)) {
+ 	ossl_raise(eX509NameError, NULL);
+     }
+@@ -425,7 +440,7 @@ ossl_x509name_to_der(VALUE self)
+  */
+ 
+ void
+-Init_ossl_x509name()
++Init_ossl_x509name(void)
+ {
+     VALUE utf8str, ptrstr, ia5str, hash;
+ 
+diff --git a/ext/openssl_cms/ossl_x509req.c b/ext/openssl_cms/ossl_x509req.c
+index 5927f76..529b685 100644
+--- a/ext/openssl_cms/ossl_x509req.c
++++ b/ext/openssl_cms/ossl_x509req.c
+@@ -14,10 +14,10 @@
+     if (!(req)) { \
+ 	ossl_raise(rb_eRuntimeError, "Req wasn't initialized!"); \
+     } \
+-    (obj) = Data_Wrap_Struct((klass), 0, X509_REQ_free, (req)); \
++    (obj) = TypedData_Wrap_Struct((klass), &ossl_x509req_type, (req)); \
+ } while (0)
+ #define GetX509Req(obj, req) do { \
+-    Data_Get_Struct((obj), X509_REQ, (req)); \
++    TypedData_Get_Struct((obj), X509_REQ, &ossl_x509req_type, (req)); \
+     if (!(req)) { \
+ 	ossl_raise(rb_eRuntimeError, "Req wasn't initialized!"); \
+     } \
+@@ -33,6 +33,20 @@
+ VALUE cX509Req;
+ VALUE eX509ReqError;
+ 
++static void
++ossl_x509req_free(void *ptr)
++{
++    X509_REQ_free(ptr);
++}
++
++static const rb_data_type_t ossl_x509req_type = {
++    "OpenSSL/X509/REQ",
++    {
++	0, ossl_x509req_free,
++    },
++    0, 0, RUBY_TYPED_FREE_IMMEDIATELY,
++};
++
+ /*
+  * Public functions
+  */
+@@ -438,7 +452,7 @@ ossl_x509req_add_attribute(VALUE self, VALUE attr)
+  * X509_REQUEST init
+  */
+ void
+-Init_ossl_x509req()
++Init_ossl_x509req(void)
+ {
+     eX509ReqError = rb_define_class_under(mX509, "RequestError", eOSSLError);
+ 
+diff --git a/ext/openssl_cms/ossl_x509revoked.c b/ext/openssl_cms/ossl_x509revoked.c
+index 320abaa..30c362c 100644
+--- a/ext/openssl_cms/ossl_x509revoked.c
++++ b/ext/openssl_cms/ossl_x509revoked.c
+@@ -14,10 +14,10 @@
+     if (!(rev)) { \
+ 	ossl_raise(rb_eRuntimeError, "REV wasn't initialized!"); \
+     } \
+-    (obj) = Data_Wrap_Struct((klass), 0, X509_REVOKED_free, (rev)); \
++    (obj) = TypedData_Wrap_Struct((klass), &ossl_x509rev_type, (rev)); \
+ } while (0)
+ #define GetX509Rev(obj, rev) do { \
+-    Data_Get_Struct((obj), X509_REVOKED, (rev)); \
++    TypedData_Get_Struct((obj), X509_REVOKED, &ossl_x509rev_type, (rev)); \
+     if (!(rev)) { \
+ 	ossl_raise(rb_eRuntimeError, "REV wasn't initialized!"); \
+     } \
+@@ -33,6 +33,20 @@
+ VALUE cX509Rev;
+ VALUE eX509RevError;
+ 
++static void
++ossl_x509rev_free(void *ptr)
++{
++    X509_REVOKED_free(ptr);
++}
++
++static const rb_data_type_t ossl_x509rev_type = {
++    "OpenSSL/X509/REV",
++    {
++	0, ossl_x509rev_free,
++    },
++    0, 0, RUBY_TYPED_FREE_IMMEDIATELY,
++};
++
+ /*
+  * PUBLIC
+  */
+@@ -209,7 +223,7 @@ ossl_x509revoked_add_extension(VALUE self, VALUE ext)
+  * INIT
+  */
+ void
+-Init_ossl_x509revoked()
++Init_ossl_x509revoked(void)
+ {
+     eX509RevError = rb_define_class_under(mX509, "RevokedError", eOSSLError);
+ 
+diff --git a/ext/openssl_cms/ossl_x509store.c b/ext/openssl_cms/ossl_x509store.c
+index f59c376..3093e28 100644
+--- a/ext/openssl_cms/ossl_x509store.c
++++ b/ext/openssl_cms/ossl_x509store.c
+@@ -14,10 +14,10 @@
+     if (!(st)) { \
+ 	ossl_raise(rb_eRuntimeError, "STORE wasn't initialized!"); \
+     } \
+-    (obj) = Data_Wrap_Struct((klass), 0, X509_STORE_free, (st)); \
++    (obj) = TypedData_Wrap_Struct((klass), &ossl_x509store_type, (st)); \
+ } while (0)
+ #define GetX509Store(obj, st) do { \
+-    Data_Get_Struct((obj), X509_STORE, (st)); \
++    TypedData_Get_Struct((obj), X509_STORE, &ossl_x509store_type, (st)); \
+     if (!(st)) { \
+ 	ossl_raise(rb_eRuntimeError, "STORE wasn't initialized!"); \
+     } \
+@@ -31,10 +31,10 @@
+     if (!(ctx)) { \
+ 	ossl_raise(rb_eRuntimeError, "STORE_CTX wasn't initialized!"); \
+     } \
+-    (obj) = Data_Wrap_Struct((klass), 0, ossl_x509stctx_free, (ctx)); \
++    (obj) = TypedData_Wrap_Struct((klass), &ossl_x509stctx_type, (ctx)); \
+ } while (0)
+ #define GetX509StCtx(obj, ctx) do { \
+-    Data_Get_Struct((obj), X509_STORE_CTX, (ctx)); \
++    TypedData_Get_Struct((obj), X509_STORE_CTX, &ossl_x509stctx_type, (ctx)); \
+     if (!(ctx)) { \
+ 	ossl_raise(rb_eRuntimeError, "STORE_CTX is out of scope!"); \
+     } \
+@@ -51,6 +51,20 @@ VALUE cX509Store;
+ VALUE cX509StoreContext;
+ VALUE eX509StoreError;
+ 
++static void
++ossl_x509store_free(void *ptr)
++{
++    X509_STORE_free(ptr);
++}
++
++static const rb_data_type_t ossl_x509store_type = {
++    "OpenSSL/X509/STORE",
++    {
++	0, ossl_x509store_free,
++    },
++    0, 0, RUBY_TYPED_FREE_IMMEDIATELY,
++};
++
+ /*
+  * Public functions
+  */
+@@ -342,7 +356,17 @@ ossl_x509store_verify(int argc, VALUE *argv, VALUE self)
+ /*
+  * Public Functions
+  */
+-static void ossl_x509stctx_free(X509_STORE_CTX*);
++static void ossl_x509stctx_free(void*);
++
++
++static const rb_data_type_t ossl_x509stctx_type = {
++    "OpenSSL/X509/STORE_CTX",
++    {
++	0, ossl_x509stctx_free,
++    },
++    0, 0, RUBY_TYPED_FREE_IMMEDIATELY,
++};
++
+ 
+ VALUE
+ ossl_x509stctx_new(X509_STORE_CTX *ctx)
+@@ -367,8 +391,9 @@ ossl_x509stctx_clear_ptr(VALUE obj)
+  * Private functions
+  */
+ static void
+-ossl_x509stctx_free(X509_STORE_CTX *ctx)
++ossl_x509stctx_free(void *ptr)
+ {
++    X509_STORE_CTX *ctx = ptr;
+     if(ctx->untrusted)
+ 	sk_X509_pop_free(ctx->untrusted, X509_free);
+     if(ctx->cert)
+@@ -593,7 +618,7 @@ ossl_x509stctx_set_time(VALUE self, VALUE time)
+  * INIT
+  */
+ void
+-Init_ossl_x509store()
++Init_ossl_x509store(void)
+ {
+     VALUE x509stctx;
+ 
+diff --git a/lib/openssl_cms/bn.rb b/lib/openssl_cms/bn.rb
+index 0e19c20..95babb4 100644
+--- a/lib/openssl_cms/bn.rb
++++ b/lib/openssl_cms/bn.rb
+@@ -21,6 +21,13 @@
+ module OpenSSL
+   class BN
+     include Comparable
++
++    def pretty_print(q)
++      q.object_group(self) {
++        q.text ' '
++        q.text to_i.to_s
++      }
++    end
+   end # BN
+ end # OpenSSL
+ 
+diff --git a/lib/openssl_cms/ssl-internal.rb b/lib/openssl_cms/ssl-internal.rb
+index cb5887e..83a2bf5 100644
+--- a/lib/openssl_cms/ssl-internal.rb
++++ b/lib/openssl_cms/ssl-internal.rb
+@@ -235,8 +235,12 @@ module OpenSSL
+           ssl.sync_close = true
+           ssl.accept if @start_immediately
+           ssl
+-        rescue SSLError => ex
+-          sock.close
++        rescue Exception => ex
++          if ssl
++            ssl.close
++          else
++            sock.close
++          end
+           raise ex
+         end
+       end
+diff --git a/lib/openssl_cms/x509-internal.rb b/lib/openssl_cms/x509-internal.rb
+index 31a4381..38b65c7 100644
+--- a/lib/openssl_cms/x509-internal.rb
++++ b/lib/openssl_cms/x509-internal.rb
+@@ -70,7 +70,7 @@ module OpenSSL
+         HexPair = /#{HexChar}#{HexChar}/
+         HexString = /#{HexPair}+/
+         Pair = /\\(?:[#{Special}]|\\|"|#{HexPair})/
+-        StringChar = /[^#{Special}\\"]/
++        StringChar = /[^\\"#{Special}]/
+         QuoteChar = /[^\\"]/
+         AttributeType = /[a-zA-Z][0-9a-zA-Z]*|[0-9]+(?:\.[0-9]+)*/
+         AttributeValue = /
+@@ -151,6 +151,13 @@ module OpenSSL
+ 
+         alias parse parse_openssl
+       end
++
++      def pretty_print(q)
++        q.object_group(self) {
++          q.text ' '
++          q.text to_s(OpenSSL::X509::Name::RFC2253)
++        }
++      end
+     end
+ 
+     class StoreContext
+@@ -158,5 +165,18 @@ module OpenSSL
+         warn "(#{caller.first}) OpenSSL::X509::StoreContext#cleanup is deprecated with no replacement" if $VERBOSE
+       end
+     end
++
++    class Certificate
++      def pretty_print(q)
++        q.object_group(self) {
++          q.breakable
++          q.text 'subject='; q.pp self.subject; q.text ','; q.breakable
++          q.text 'issuer='; q.pp self.issuer; q.text ','; q.breakable
++          q.text 'serial='; q.pp self.serial; q.text ','; q.breakable
++          q.text 'not_before='; q.pp self.not_before; q.text ','; q.breakable
++          q.text 'not_after='; q.pp self.not_after
++        }
++      end
++    end
+   end
+ end
diff --git a/rubygem-openssl_cms.spec b/rubygem-openssl_cms.spec
index 1caf0ae..96473cd 100644
--- a/rubygem-openssl_cms.spec
+++ b/rubygem-openssl_cms.spec
@@ -1,6 +1,7 @@
 %global gem_basename openssl_cms
-%global gem_rubyver 2_1
+%global gem_rubyver 2_2
 %global gem_name %{gem_basename}_%{gem_rubyver}
+%global gem_srcname %{gem_basename}_2_1
 
 %global commit b789b696d821bd6563dd207fb6b562c06acc835b
 %global shortcommit %(c=%{commit}; echo ${c:0:7})
@@ -24,25 +25,28 @@ URL:            https://github.com/arax/openssl-cms
 # gem build ${gem_basename}.gemspec
 # gem spec ${gem_name}-${version}.gem -l --ruby > ${gem_basename}.gemspec
 # gem build ${gem_basename}.gemspec
-Source0:        %{gem_name}-%{version}.gem
+Source0:        %{gem_srcname}-%{version}.gem
 Source1:        https://raw.githubusercontent.com/arax/openssl-cms/master/README.md
+# https://github.com/arax/openssl-cms/pull/1
+Patch0:        openssl_cms-ruby2.1.5.diff
+Patch1:        openssl_cms-ruby2.2.0.diff
 
 BuildRequires:  openssl-devel
 BuildRequires:  ruby(release)
 BuildRequires:  rubygems-devel
-BuildRequires:  ruby-devel => 2.1
+BuildRequires:  ruby-devel => 2.2
 
 %description
 OpenSSL with Cryptographic Message Syntax functions for Ruby.
 
 
 %package -n rubygem-%{gem_name}
-Summary:        OpenSSL with CMS functions for Ruby 2.1
+Summary:        OpenSSL with CMS functions for Ruby 2.2
 Group:          Development/Languages
-Requires:       ruby(release) >= 2.1
+Requires:       ruby(release) >= 2.2
 
 %description -n rubygem-%{gem_name}
-OpenSSL with Cryptographic Message Syntax functions for Ruby 2.1.
+OpenSSL with Cryptographic Message Syntax functions for Ruby 2.2.
 
 
 %package -n rubygem-%{gem_name}-doc
@@ -57,10 +61,18 @@ Documentation for %{name}.
 
 %prep
 gem unpack %{SOURCE0}
-%setup -q -D -T -n  %{gem_name}-%{version}
+%setup -q -D -T -n  %{gem_srcname}-%{version}
+
+%patch0 -p1
+%patch1 -p1
 
 gem spec %{SOURCE0} -l --ruby > %{gem_name}.gemspec
 
+# update for ruby 2.2
+sed -i %{gem_name}.gemspec \
+  -e 's,name = ".*",name = "openssl_cms_2_2",' \
+  -e 's,\(required_ruby_version.*\)"~> 2.1.0",\1"~> 2.2.0",'
+
 # README.md
 cp -p %{SOURCE1} .
 
@@ -90,21 +102,24 @@ rm -rf %{buildroot}%{gem_instdir}/ext/
 %files -n rubygem-%{gem_name}
 %license %{gem_instdir}/BSDL
 %license %{gem_instdir}/LICENSE
-%dir %{gem_instdir}
-%{gem_libdir}
-%{gem_extdir_mri}
+%dir %{gem_instdir}/
+%{gem_libdir}/
+%{gem_extdir_mri}/
 %exclude %{gem_cache}
 %{gem_spec}
 %exclude %{gem_instdir}/.gitignore
 
 %files -n rubygem-%{gem_name}-doc
-%doc %{gem_docdir}
+%doc %{gem_docdir}/
 %{gem_instdir}/README.md
 %exclude %{gem_instdir}/%{gem_basename}.gemspec
 
 
 %changelog
-* Sun Jan 18 2015 Mamoru TASAKA <mtasaka at fedoraproject.org> - 0.0.3-2.20140212git7fea071
+* Wed Jan 28 2015 František Dvořák <valtri at civ.zcu.cz> - 0.0.2-3.20140212gitb789b69
+- Add support for ruby 2.2
+
+* Sun Jan 18 2015 Mamoru TASAKA <mtasaka at fedoraproject.org> - 0.0.2-3.20140212git7fea071
 - Rebuild for https://fedoraproject.org/wiki/Changes/Ruby_2.2
 
 * Wed Oct 08 2014 František Dvořák <valtri at civ.zcu.cz> - 0.0.2-2.20140212git7fea071


More information about the scm-commits mailing list