summaryrefslogtreecommitdiff
path: root/ext
diff options
context:
space:
mode:
authorrhe <rhe@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2016-11-30 14:41:46 +0000
committerrhe <rhe@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2016-11-30 14:41:46 +0000
commitaab0d67a1ff5190ff7a951e40cee742210302aed (patch)
treec8635fd674d8300fa79e76a2f5d5eeef465abd88 /ext
parent0a5abaf745bf40de27bf4fac2172aaeacc2e2637 (diff)
openssl: import v2.0.0
Import Ruby/OpenSSL 2.0.0. The full commit history since 2.0.0 beta.2 (imported at r56098) can be found at: https://github.com/ruby/openssl/compare/v2.0.0.beta.2...v2.0.0 git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@56946 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'ext')
-rw-r--r--ext/openssl/History.md137
-rw-r--r--ext/openssl/extconf.rb6
-rw-r--r--ext/openssl/lib/openssl/buffering.rb8
-rw-r--r--ext/openssl/lib/openssl/ssl.rb20
-rw-r--r--ext/openssl/openssl.gemspec28
-rw-r--r--ext/openssl/ossl.c115
-rw-r--r--ext/openssl/ossl.h42
-rw-r--r--ext/openssl/ossl_asn1.c198
-rw-r--r--ext/openssl/ossl_bio.c3
-rw-r--r--ext/openssl/ossl_bn.c17
-rw-r--r--ext/openssl/ossl_cipher.c77
-rw-r--r--ext/openssl/ossl_digest.c37
-rw-r--r--ext/openssl/ossl_engine.c19
-rw-r--r--ext/openssl/ossl_ns_spki.c7
-rw-r--r--ext/openssl/ossl_pkcs7.c2
-rw-r--r--ext/openssl/ossl_pkey.c107
-rw-r--r--ext/openssl/ossl_pkey.h1
-rw-r--r--ext/openssl/ossl_pkey_dh.c2
-rw-r--r--ext/openssl/ossl_pkey_dsa.c6
-rw-r--r--ext/openssl/ossl_pkey_ec.c62
-rw-r--r--ext/openssl/ossl_pkey_rsa.c12
-rw-r--r--ext/openssl/ossl_ssl.c178
-rw-r--r--ext/openssl/ossl_ssl_session.c55
-rw-r--r--ext/openssl/ossl_x509.h9
-rw-r--r--ext/openssl/ossl_x509cert.c2
-rw-r--r--ext/openssl/ossl_x509crl.c29
-rw-r--r--ext/openssl/ossl_x509name.c8
-rw-r--r--ext/openssl/ossl_x509req.c22
-rw-r--r--ext/openssl/ossl_x509store.c108
-rw-r--r--ext/openssl/ruby_missing.h9
30 files changed, 680 insertions, 646 deletions
diff --git a/ext/openssl/History.md b/ext/openssl/History.md
new file mode 100644
index 0000000..029426f
--- /dev/null
+++ b/ext/openssl/History.md
@@ -0,0 +1,137 @@
+Version 2.0.0
+=============
+
+This is the first release of openssl gem, formerly a standard library of Ruby,
+ext/openssl. This is the successor of the version included in Ruby 2.3.
+
+Compatibility notes
+-------------------
+
+* Support for OpenSSL version 0.9.6 and 0.9.7 is completely removed. openssl gem
+ still works with OpenSSL 0.9.8, but users are strongly encouraged to upgrade
+ to at least 1.0.1, as OpenSSL < 1.0.1 will not receive any security fixes from
+ the OpenSSL development team.
+
+Supported platforms
+-------------------
+
+* OpenSSL 1.0.0, 1.0.1, 1.0.2, 1.1.0
+* OpenSSL < 0.9.8 is no longer supported.
+* LibreSSL 2.3, 2.4, 2.5
+* Ruby 2.3, 2.4
+
+Notable changes
+---------------
+
+* Add support for OpenSSL 1.1.0. [[Feature #12324]](https://bugs.ruby-lang.org/issues/12324)
+* Add support for LibreSSL
+
+* OpenSSL::Cipher
+
+ - OpenSSL::Cipher#key= and #iv= reject too long inputs. They used to truncate
+ silently. [[Bug #12561]](https://bugs.ruby-lang.org/issues/12561)
+
+ - OpenSSL::Cipher#iv_len= is added. It allows changing IV (nonce) length if
+ using AEAD ciphers.
+ [[Bug #8667]](https://bugs.ruby-lang.org/issues/8667),
+ [[Bug #10420]](https://bugs.ruby-lang.org/issues/10420),
+ [[GH ruby/ruby#569]](https://github.com/ruby/ruby/pull/569),
+ [[GH ruby/openssl#58]](https://github.com/ruby/openssl/pull/58)
+
+ - OpenSSL::Cipher#auth_tag_len= is added. This sets the authentication tag
+ length to be generated by an AEAD cipher.
+
+* OpenSSL::OCSP
+
+ - Accessor methods are added to OpenSSL::OCSP::CertificateId.
+ [[Feature #7181]](https://bugs.ruby-lang.org/issues/7181)
+
+ - OpenSSL::OCSP::Request and BasicResponse can be signed with non-SHA-1 hash
+ algorithm. [[Feature #11552]](https://bugs.ruby-lang.org/issues/11552)
+
+ - OpenSSL::OCSP::CertificateId and BasicResponse can be encoded into DER.
+
+ - A new class OpenSSL::OCSP::SingleResponse is added for convenience.
+
+ - OpenSSL::OCSP::BasicResponse#add_status accepts absolute times. They used to
+ accept only relative seconds from the current time.
+
+* OpenSSL::PKey
+
+ - OpenSSL::PKey::EC follows the general PKey interface.
+ [[Bug #6567]](https://bugs.ruby-lang.org/issues/6567)
+
+ - OpenSSL::PKey.read raises OpenSSL::PKey::PKeyError instead of ArgumentError
+ for consistency with OpenSSL::PKey::{DH,DSA,RSA,EC}#new.
+ [[Bug #11774]](https://bugs.ruby-lang.org/issues/11774),
+ [[GH ruby/openssl#55]](https://github.com/ruby/openssl/pull/55)
+
+ - OpenSSL::PKey::EC::Group retrieved by OpenSSL::PKey::EC#group is no longer
+ linked with the EC key. Modifications to the EC::Group have no effect on the
+ key. [[GH ruby/openssl#71]](https://github.com/ruby/openssl/pull/71)
+
+ - OpenSSL::PKey::EC::Point#to_bn allows specifying the point conversion form
+ by the optional argument.
+
+* OpenSSL::SSL
+
+ - OpenSSL::SSL::SSLSocket#tmp_key is added. A client can call it after the
+ connection is established to retrieve the ephemeral key.
+ [[GH ruby/ruby#1318]](https://github.com/ruby/ruby/pull/1318)
+
+ - The automatic ephemeral ECDH curve selection is enabled by default when
+ built with OpenSSL >= 1.0.2 or LibreSSL.
+
+ - OpenSSL::SSL::SSLContext#security_level= is added. You can set the "security
+ level" of the SSL context. This is effective only when built with OpenSSL
+ 1.1.0.
+
+ - A new option 'verify_hostname' is added to OpenSSL::SSL::SSLContext. When it
+ is enabled, and the SNI hostname is also set, the hostname verification on
+ the server certificate is automatically performed. It is now enabled by
+ OpenSSL::SSL::Context#set_params.
+ [[GH ruby/openssl#60]](https://github.com/ruby/openssl/pull/60)
+
+Removals
+--------
+
+* OpenSSL::Engine
+
+ - OpenSSL::Engine.cleanup does nothing when built with OpenSSL 1.1.0.
+
+* OpenSSL::SSL
+
+ - OpenSSL::PKey::DH::DEFAULT_512 is removed. Hence servers no longer use
+ 512-bit DH group by default. It is considered too weak nowadays.
+ [[Bug #11968]](https://bugs.ruby-lang.org/issues/11968),
+ [[GH ruby/ruby#1196]](https://github.com/ruby/ruby/pull/1196)
+
+ - RC4 cipher suites are removed from OpenSSL::SSL::SSLContext::DEFAULT_PARAMS.
+ RC4 is now considered to be weak.
+ [[GH ruby/openssl#50]](https://github.com/ruby/openssl/pull/50)
+
+Deprecations
+------------
+
+* OpenSSL::PKey
+
+ - OpenSSL::PKey::RSA#n=, #e=, #d=, #p=, #q=, #dmp1=, #dmq1=, #iqmp=,
+ OpenSSL::PKey::DSA#p=, #q=, #g=, #priv_key=, #pub_key=,
+ OpenSSL::PKey::DH#p=, #g=, #priv_key= and #pub_key= are deprecated. They are
+ disabled when built with OpenSSL 1.1.0, due to its API change. Instead,
+ OpenSSL::PKey::RSA#set_key, #set_factors, #set_crt_params,
+ OpenSSL::PKey::DSA#set_pqg, #set_key, OpenSSL::PKey::DH#set_pqg and #set_key
+ are added.
+
+* OpenSSL::Random
+
+ - OpenSSL::Random.pseudo_bytes is deprecated, and not defined when built with
+ OpenSSL 1.1.0. Use OpenSSL::Random.random_bytes instead.
+
+* OpenSSL::SSL
+
+ - OpenSSL::SSL::SSLContext#tmp_ecdh_callback is deprecated, as the underlying
+ API SSL_CTX_set_tmp_ecdh_callback() is removed in OpenSSL 1.1.0. It was
+ first added in Ruby 2.3.0. To specify the curve to be used in ephemeral
+ ECDH, use OpenSSL::SSL::SSLContext#ecdh_curves=. The automatic curve
+ selection is also now enabled by default when built with a capable OpenSSL.
diff --git a/ext/openssl/extconf.rb b/ext/openssl/extconf.rb
index 20c67c6..a812e59 100644
--- a/ext/openssl/extconf.rb
+++ b/ext/openssl/extconf.rb
@@ -33,14 +33,8 @@ end
Logging::message "=== Checking for system dependent stuff... ===\n"
have_library("nsl", "t_open")
have_library("socket", "socket")
-have_header("assert.h")
Logging::message "=== Checking for required stuff... ===\n"
-if $mingw
- have_library("wsock32")
- have_library("gdi32")
-end
-
result = pkg_config("openssl") && have_header("openssl/ssl.h")
unless result
result = have_header("openssl/ssl.h")
diff --git a/ext/openssl/lib/openssl/buffering.rb b/ext/openssl/lib/openssl/buffering.rb
index 94aba35..7fd647c 100644
--- a/ext/openssl/lib/openssl/buffering.rb
+++ b/ext/openssl/lib/openssl/buffering.rb
@@ -163,6 +163,10 @@ module OpenSSL::Buffering
# Note that one reason that read_nonblock writes to the underlying IO is
# when the peer requests a new TLS/SSL handshake. See openssl the FAQ for
# more details. http://www.openssl.org/support/faq.html
+ #
+ # By specifying `exception: false`, the options hash allows you to indicate
+ # that read_nonblock should not raise an IO::Wait*able exception, but
+ # return the symbol :wait_writable or :wait_readable instead.
def read_nonblock(maxlen, buf=nil, exception: true)
if maxlen == 0
@@ -371,6 +375,10 @@ module OpenSSL::Buffering
# Note that one reason that write_nonblock reads from the underlying IO
# is when the peer requests a new TLS/SSL handshake. See the openssl FAQ
# for more details. http://www.openssl.org/support/faq.html
+ #
+ # By specifying `exception: false`, the options hash allows you to indicate
+ # that write_nonblock should not raise an IO::Wait*able exception, but
+ # return the symbol :wait_writable or :wait_readable instead.
def write_nonblock(s, exception: true)
flush
diff --git a/ext/openssl/lib/openssl/ssl.rb b/ext/openssl/lib/openssl/ssl.rb
index 190f504..f40a451 100644
--- a/ext/openssl/lib/openssl/ssl.rb
+++ b/ext/openssl/lib/openssl/ssl.rb
@@ -16,8 +16,7 @@ require "io/nonblock"
module OpenSSL
module SSL
class SSLContext
- # :nodoc:
- DEFAULT_PARAMS = {
+ DEFAULT_PARAMS = { # :nodoc:
:ssl_version => "SSLv23",
:verify_mode => OpenSSL::SSL::VERIFY_PEER,
:verify_hostname => true,
@@ -68,8 +67,7 @@ module OpenSSL
)
end
- # :nodoc:
- DEFAULT_CERT_STORE = OpenSSL::X509::Store.new
+ DEFAULT_CERT_STORE = OpenSSL::X509::Store.new # :nodoc:
DEFAULT_CERT_STORE.set_default_paths
DEFAULT_CERT_STORE.flags = OpenSSL::X509::V_FLAG_CRL_CHECK_ALL
@@ -84,14 +82,12 @@ module OpenSSL
attr_accessor :tmp_dh_callback
- if ExtConfig::HAVE_TLSEXT_HOST_NAME
- # A callback invoked at connect time to distinguish between multiple
- # server names.
- #
- # The callback is invoked with an SSLSocket and a server name. The
- # callback must return an SSLContext for the server name or nil.
- attr_accessor :servername_cb
- end
+ # A callback invoked at connect time to distinguish between multiple
+ # server names.
+ #
+ # The callback is invoked with an SSLSocket and a server name. The
+ # callback must return an SSLContext for the server name or nil.
+ attr_accessor :servername_cb if ExtConfig::HAVE_TLSEXT_HOST_NAME
# call-seq:
# SSLContext.new => ctx
diff --git a/ext/openssl/openssl.gemspec b/ext/openssl/openssl.gemspec
index 48191fa..2390da4 100644
--- a/ext/openssl/openssl.gemspec
+++ b/ext/openssl/openssl.gemspec
@@ -1,15 +1,15 @@
# -*- encoding: utf-8 -*-
-# stub: openssl 2.0.0.beta.2 ruby lib
+# stub: openssl 2.0.0 ruby lib
# stub: ext/openssl/extconf.rb
Gem::Specification.new do |s|
s.name = "openssl".freeze
- s.version = "2.0.0.beta.2"
+ s.version = "2.0.0"
- s.required_rubygems_version = Gem::Requirement.new("> 1.3.1".freeze) if s.respond_to? :required_rubygems_version=
+ s.required_rubygems_version = Gem::Requirement.new(">= 0".freeze) if s.respond_to? :required_rubygems_version=
s.require_paths = ["lib".freeze]
s.authors = ["Martin Bosslet".freeze, "SHIBATA Hiroshi".freeze, "Zachary Scott".freeze, "Kazuki Yamaguchi".freeze]
- s.date = "2016-09-08"
+ s.date = "2016-11-30"
s.description = "It wraps the OpenSSL library.".freeze
s.email = ["ruby-core@ruby-lang.org".freeze]
s.extensions = ["ext/openssl/extconf.rb".freeze]
@@ -19,27 +19,27 @@ Gem::Specification.new do |s|
s.licenses = ["Ruby".freeze]
s.rdoc_options = ["--main".freeze, "README.md".freeze]
s.required_ruby_version = Gem::Requirement.new(">= 2.3.0".freeze)
- s.rubygems_version = "2.6.6".freeze
+ s.rubygems_version = "2.6.8".freeze
s.summary = "OpenSSL provides SSL, TLS and general purpose cryptography.".freeze
if s.respond_to? :specification_version then
s.specification_version = 4
if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
- s.add_development_dependency(%q<rake>.freeze, ["~> 10.3"])
- s.add_development_dependency(%q<rake-compiler>.freeze, ["~> 0.9"])
+ s.add_development_dependency(%q<rake>.freeze, [">= 0"])
+ s.add_development_dependency(%q<rake-compiler>.freeze, [">= 0"])
s.add_development_dependency(%q<test-unit>.freeze, ["~> 3.0"])
- s.add_development_dependency(%q<rdoc>.freeze, ["~> 4.2"])
+ s.add_development_dependency(%q<rdoc>.freeze, [">= 0"])
else
- s.add_dependency(%q<rake>.freeze, ["~> 10.3"])
- s.add_dependency(%q<rake-compiler>.freeze, ["~> 0.9"])
+ s.add_dependency(%q<rake>.freeze, [">= 0"])
+ s.add_dependency(%q<rake-compiler>.freeze, [">= 0"])
s.add_dependency(%q<test-unit>.freeze, ["~> 3.0"])
- s.add_dependency(%q<rdoc>.freeze, ["~> 4.2"])
+ s.add_dependency(%q<rdoc>.freeze, [">= 0"])
end
else
- s.add_dependency(%q<rake>.freeze, ["~> 10.3"])
- s.add_dependency(%q<rake-compiler>.freeze, ["~> 0.9"])
+ s.add_dependency(%q<rake>.freeze, [">= 0"])
+ s.add_dependency(%q<rake-compiler>.freeze, [">= 0"])
s.add_dependency(%q<test-unit>.freeze, ["~> 3.0"])
- s.add_dependency(%q<rdoc>.freeze, ["~> 4.2"])
+ s.add_dependency(%q<rdoc>.freeze, [">= 0"])
end
end
diff --git a/ext/openssl/ossl.c b/ext/openssl/ossl.c
index a9000f2..8269599 100644
--- a/ext/openssl/ossl.c
+++ b/ext/openssl/ossl.c
@@ -149,7 +149,7 @@ ossl_pem_passwd_value(VALUE pass)
/* PEM_BUFSIZE is currently used as the second argument of pem_password_cb,
* that is +max_len+ of ossl_pem_passwd_cb() */
if (RSTRING_LEN(pass) > PEM_BUFSIZE)
- ossl_raise(eOSSLError, "password must be shorter than %d bytes", PEM_BUFSIZE);
+ ossl_raise(eOSSLError, "password must not be longer than %d bytes", PEM_BUFSIZE);
return pass;
}
@@ -168,7 +168,8 @@ ossl_pem_passwd_cb0(VALUE flag)
int
ossl_pem_passwd_cb(char *buf, int max_len, int flag, void *pwd_)
{
- int len, status;
+ long len;
+ int status;
VALUE rflag, pass = (VALUE)pwd_;
if (RTEST(pass)) {
@@ -176,7 +177,7 @@ ossl_pem_passwd_cb(char *buf, int max_len, int flag, void *pwd_)
* work because it does not allow NUL characters and truncates to 1024
* bytes silently if the input is over 1024 bytes */
if (RB_TYPE_P(pass, T_STRING)) {
- len = RSTRING_LENINT(pass);
+ len = RSTRING_LEN(pass);
if (len >= OSSL_MIN_PWD_LEN && len <= max_len) {
memcpy(buf, RSTRING_PTR(pass), len);
return len;
@@ -203,78 +204,19 @@ ossl_pem_passwd_cb(char *buf, int max_len, int flag, void *pwd_)
rb_set_errinfo(Qnil);
return -1;
}
- len = RSTRING_LENINT(pass);
+ len = RSTRING_LEN(pass);
if (len < OSSL_MIN_PWD_LEN) {
rb_warning("password must be at least %d bytes", OSSL_MIN_PWD_LEN);
continue;
}
if (len > max_len) {
- rb_warning("password must be shorter than %d bytes", max_len);
+ rb_warning("password must not be longer than %d bytes", max_len);
continue;
}
memcpy(buf, RSTRING_PTR(pass), len);
break;
}
- return len;
-}
-
-/*
- * Verify callback
- */
-int ossl_store_ctx_ex_verify_cb_idx;
-int ossl_store_ex_verify_cb_idx;
-
-struct ossl_verify_cb_args {
- VALUE proc;
- VALUE preverify_ok;
- VALUE store_ctx;
-};
-
-static VALUE
-ossl_call_verify_cb_proc(struct ossl_verify_cb_args *args)
-{
- return rb_funcall(args->proc, rb_intern("call"), 2,
- args->preverify_ok, args->store_ctx);
-}
-
-int
-ossl_verify_cb_call(VALUE proc, int ok, X509_STORE_CTX *ctx)
-{
- VALUE rctx, ret;
- struct ossl_verify_cb_args args;
- int state;
-
- if (NIL_P(proc))
- return ok;
-
- ret = Qfalse;
- rctx = rb_protect((VALUE(*)(VALUE))ossl_x509stctx_new, (VALUE)ctx, &state);
- if (state) {
- rb_set_errinfo(Qnil);
- rb_warn("StoreContext initialization failure");
- }
- else {
- args.proc = proc;
- args.preverify_ok = ok ? Qtrue : Qfalse;
- args.store_ctx = rctx;
- ret = rb_protect((VALUE(*)(VALUE))ossl_call_verify_cb_proc, (VALUE)&args, &state);
- if (state) {
- rb_set_errinfo(Qnil);
- rb_warn("exception in verify_callback is ignored");
- }
- ossl_x509stctx_clear_ptr(rctx);
- }
- if (ret == Qtrue) {
- X509_STORE_CTX_set_error(ctx, X509_V_OK);
- ok = 1;
- }
- else {
- if (X509_STORE_CTX_get_error(ctx) == X509_V_OK)
- X509_STORE_CTX_set_error(ctx, X509_V_ERR_CERT_REJECTED);
- ok = 0;
- }
-
- return ok;
+ return (int)len;
}
/*
@@ -355,27 +297,32 @@ ossl_raise(VALUE exc, const char *fmt, ...)
rb_exc_raise(err);
}
-VALUE
-ossl_exc_new(VALUE exc, const char *fmt, ...)
-{
- va_list args;
- VALUE err;
- va_start(args, fmt);
- err = ossl_make_error(exc, fmt, args);
- va_end(args);
- return err;
-}
-
void
ossl_clear_error(void)
{
if (dOSSL == Qtrue) {
- long e;
- while ((e = ERR_get_error())) {
- rb_warn("error on stack: %s", ERR_error_string(e, NULL));
+ unsigned long e;
+ const char *file, *data, *errstr;
+ int line, flags;
+
+ while ((e = ERR_get_error_line_data(&file, &line, &data, &flags))) {
+ errstr = ERR_error_string(e, NULL);
+ if (!errstr)
+ errstr = "(null)";
+
+ if (flags & ERR_TXT_STRING) {
+ if (!data)
+ data = "(null)";
+ rb_warn("error on stack: %s (%s)", errstr, data);
+ }
+ else {
+ rb_warn("error on stack: %s", errstr);
+ }
}
}
- ERR_clear_error();
+ else {
+ ERR_clear_error();
+ }
}
/*
@@ -1152,14 +1099,6 @@ Init_openssl(void)
rb_define_module_function(mOSSL, "errors", ossl_get_errors, 0);
/*
- * Verify callback Proc index for ext-data
- */
- if ((ossl_store_ctx_ex_verify_cb_idx = X509_STORE_CTX_get_ex_new_index(0, (void *)"ossl_store_ctx_ex_verify_cb_idx", 0, 0, 0)) < 0)
- ossl_raise(eOSSLError, "X509_STORE_CTX_get_ex_new_index");
- if ((ossl_store_ex_verify_cb_idx = X509_STORE_get_ex_new_index(0, (void *)"ossl_store_ex_verify_cb_idx", 0, 0, 0)) < 0)
- ossl_raise(eOSSLError, "X509_STORE_get_ex_new_index");
-
- /*
* Get ID of to_der
*/
ossl_s_to_der = rb_intern("to_der");
diff --git a/ext/openssl/ossl.h b/ext/openssl/ossl.h
index 864d068..78eddd0 100644
--- a/ext/openssl/ossl.h
+++ b/ext/openssl/ossl.h
@@ -12,37 +12,12 @@
#include RUBY_EXTCONF_H
-#if 0
- mOSSL = rb_define_module("OpenSSL");
- mX509 = rb_define_module_under(mOSSL, "X509");
-#endif
-
-/*
-* OpenSSL has defined RFILE and Ruby has defined RFILE - so undef it!
-*/
-#if defined(RFILE) /*&& !defined(OSSL_DEBUG)*/
-# undef RFILE
-#endif
+#include <assert.h>
+#include <errno.h>
#include <ruby.h>
#include <ruby/io.h>
#include <ruby/thread.h>
-
#include <openssl/opensslv.h>
-
-#ifdef HAVE_ASSERT_H
-# include <assert.h>
-#else
-# define assert(condition)
-#endif
-
-#if defined(_WIN32) && !defined(LIBRESSL_VERSION_NUMBER)
-# include <openssl/e_os2.h>
-# if !defined(OPENSSL_SYS_WIN32)
-# define OPENSSL_SYS_WIN32 1
-# endif
-# include <winsock2.h>
-#endif
-#include <errno.h>
#include <openssl/err.h>
#include <openssl/asn1.h>
#include <openssl/x509v3.h>
@@ -53,9 +28,7 @@
#include <openssl/rand.h>
#include <openssl/conf.h>
#include <openssl/conf_api.h>
-#if !defined(_WIN32)
-# include <openssl/crypto.h>
-#endif
+#include <openssl/crypto.h>
#if !defined(OPENSSL_NO_ENGINE)
# include <openssl/engine.h>
#endif
@@ -144,19 +117,10 @@ int ossl_pem_passwd_cb(char *, int, int, void *);
*/
#define OSSL_ErrMsg() ERR_reason_error_string(ERR_get_error())
NORETURN(void ossl_raise(VALUE, const char *, ...));
-VALUE ossl_exc_new(VALUE, const char *, ...);
/* Clear OpenSSL error queue. If dOSSL is set, rb_warn() them. */
void ossl_clear_error(void);
/*
- * Verify callback
- */
-extern int ossl_store_ctx_ex_verify_cb_idx;
-extern int ossl_store_ex_verify_cb_idx;
-
-int ossl_verify_cb_call(VALUE, int, X509_STORE_CTX *);
-
-/*
* String to DER String
*/
extern ID ossl_s_to_der;
diff --git a/ext/openssl/ossl_asn1.c b/ext/openssl/ossl_asn1.c
index 85b1f02..af8ae2a 100644
--- a/ext/openssl/ossl_asn1.c
+++ b/ext/openssl/ossl_asn1.c
@@ -9,15 +9,6 @@
*/
#include "ossl.h"
-#if defined(HAVE_SYS_TIME_H)
-# include <sys/time.h>
-#elif !defined(NT) && !defined(_WIN32)
-struct timeval {
- long tv_sec; /* seconds */
- long tv_usec; /* and microseconds */
-};
-#endif
-
static VALUE join_der(VALUE enumerable);
static VALUE ossl_asn1_decode0(unsigned char **pp, long length, long *offset,
int depth, int yield, long *num_read);
@@ -110,16 +101,11 @@ asn1str_to_str(const ASN1_STRING *str)
/*
* ASN1_INTEGER conversions
- * TODO: Make a decision what's the right way to do this.
*/
-#define DO_IT_VIA_RUBY 0
VALUE
asn1integer_to_num(const ASN1_INTEGER *ai)
{
BIGNUM *bn;
-#if DO_IT_VIA_RUBY
- char *txt;
-#endif
VALUE num;
if (!ai) {
@@ -133,43 +119,12 @@ asn1integer_to_num(const ASN1_INTEGER *ai)
if (!bn)
ossl_raise(eOSSLError, NULL);
-#if DO_IT_VIA_RUBY
- if (!(txt = BN_bn2dec(bn))) {
- BN_free(bn);
- ossl_raise(eOSSLError, NULL);
- }
- num = rb_cstr_to_inum(txt, 10, Qtrue);
- OPENSSL_free(txt);
-#else
num = ossl_bn_new(bn);
-#endif
BN_free(bn);
return num;
}
-#if DO_IT_VIA_RUBY
-ASN1_INTEGER *
-num_to_asn1integer(VALUE obj, ASN1_INTEGER *ai)
-{
- BIGNUM *bn = NULL;
-
- if (RTEST(rb_obj_is_kind_of(obj, cBN))) {
- bn = GetBNPtr(obj);
- } else {
- obj = rb_String(obj);
- if (!BN_dec2bn(&bn, StringValueCStr(obj))) {
- ossl_raise(eOSSLError, NULL);
- }
- }
- if (!(ai = BN_to_ASN1_INTEGER(bn, ai))) {
- BN_free(bn);
- ossl_raise(eOSSLError, NULL);
- }
- BN_free(bn);
- return ai;
-}
-#else
ASN1_INTEGER *
num_to_asn1integer(VALUE obj, ASN1_INTEGER *ai)
{
@@ -185,7 +140,6 @@ num_to_asn1integer(VALUE obj, ASN1_INTEGER *ai)
return ai;
}
-#endif
/********/
/*
@@ -225,9 +179,10 @@ VALUE cASN1ObjectId; /* OBJECT IDENTIFIER */
VALUE cASN1UTCTime, cASN1GeneralizedTime; /* TIME */
VALUE cASN1Sequence, cASN1Set; /* CONSTRUCTIVE */
-static ID sIMPLICIT, sEXPLICIT;
-static ID sUNIVERSAL, sAPPLICATION, sCONTEXT_SPECIFIC, sPRIVATE;
+static VALUE sym_IMPLICIT, sym_EXPLICIT;
+static VALUE sym_UNIVERSAL, sym_APPLICATION, sym_CONTEXT_SPECIFIC, sym_PRIVATE;
static ID sivVALUE, sivTAG, sivTAG_CLASS, sivTAGGING, sivINFINITE_LENGTH, sivUNUSED_BITS;
+static ID id_each;
/*
* Ruby to ASN1 converters
@@ -364,13 +319,12 @@ decode_bool(unsigned char* der, long length)
{
const unsigned char *p = der;
- assert(length == 3);
- if (*p++ != 1)
- ossl_raise(eASN1Error, "not a boolean");
- if (*p++ != 1)
- ossl_raise(eASN1Error, "length is not 1");
+ if (length != 3)
+ ossl_raise(eASN1Error, "invalid length for BOOLEAN");
+ if (p[0] != 1 || p[1] != 1)
+ ossl_raise(eASN1Error, "invalid BOOLEAN");
- return *p ? Qtrue : Qfalse;
+ return p[2] ? Qtrue : Qfalse;
}
static VALUE
@@ -632,17 +586,14 @@ ossl_asn1_default_tag(VALUE obj)
VALUE tmp_class, tag;
tmp_class = CLASS_OF(obj);
- while (tmp_class) {
+ while (!NIL_P(tmp_class)) {
tag = rb_hash_lookup(class_tag_map, tmp_class);
- if (tag != Qnil) {
- return NUM2INT(tag);
- }
- tmp_class = rb_class_superclass(tmp_class);
+ if (tag != Qnil)
+ return NUM2INT(tag);
+ tmp_class = rb_class_superclass(tmp_class);
}
ossl_raise(eASN1Error, "universal tag for %"PRIsVALUE" not found",
rb_obj_class(obj));
-
- return -1; /* dummy */
}
static int
@@ -661,59 +612,45 @@ static int
ossl_asn1_is_explicit(VALUE obj)
{
VALUE s;
- int ret = -1;
s = ossl_asn1_get_tagging(obj);
- if(NIL_P(s)) return 0;
- else if(SYMBOL_P(s)){
- if (SYM2ID(s) == sIMPLICIT)
- ret = 0;
- else if (SYM2ID(s) == sEXPLICIT)
- ret = 1;
- }
- if(ret < 0){
+ if (NIL_P(s) || s == sym_IMPLICIT)
+ return 0;
+ else if (s == sym_EXPLICIT)
+ return 1;
+ else
ossl_raise(eASN1Error, "invalid tag default");
- }
-
- return ret;
}
static int
ossl_asn1_tag_class(VALUE obj)
{
VALUE s;
- int ret = -1;
s = ossl_asn1_get_tag_class(obj);
- if(NIL_P(s)) ret = V_ASN1_UNIVERSAL;
- else if(SYMBOL_P(s)){
- if (SYM2ID(s) == sUNIVERSAL)
- ret = V_ASN1_UNIVERSAL;
- else if (SYM2ID(s) == sAPPLICATION)
- ret = V_ASN1_APPLICATION;
- else if (SYM2ID(s) == sCONTEXT_SPECIFIC)
- ret = V_ASN1_CONTEXT_SPECIFIC;
- else if (SYM2ID(s) == sPRIVATE)
- ret = V_ASN1_PRIVATE;
- }
- if(ret < 0){
+ if (NIL_P(s) || s == sym_UNIVERSAL)
+ return V_ASN1_UNIVERSAL;
+ else if (s == sym_APPLICATION)
+ return V_ASN1_APPLICATION;
+ else if (s == sym_CONTEXT_SPECIFIC)
+ return V_ASN1_CONTEXT_SPECIFIC;
+ else if (s == sym_PRIVATE)
+ return V_ASN1_PRIVATE;
+ else
ossl_raise(eASN1Error, "invalid tag class");
- }
-
- return ret;
}
static VALUE
ossl_asn1_class2sym(int tc)
{
if((tc & V_ASN1_PRIVATE) == V_ASN1_PRIVATE)
- return ID2SYM(sPRIVATE);
+ return sym_PRIVATE;
else if((tc & V_ASN1_CONTEXT_SPECIFIC) == V_ASN1_CONTEXT_SPECIFIC)
- return ID2SYM(sCONTEXT_SPECIFIC);
+ return sym_CONTEXT_SPECIFIC;
else if((tc & V_ASN1_APPLICATION) == V_ASN1_APPLICATION)
- return ID2SYM(sAPPLICATION);
+ return sym_APPLICATION;
else
- return ID2SYM(sUNIVERSAL);
+ return sym_UNIVERSAL;
}
/*
@@ -737,7 +674,7 @@ ossl_asn1data_initialize(VALUE self, VALUE value, VALUE tag, VALUE tag_class)
{
if(!SYMBOL_P(tag_class))
ossl_raise(eASN1Error, "invalid tag class");
- if((SYM2ID(tag_class) == sUNIVERSAL) && NUM2INT(tag) > 31)
+ if (tag_class == sym_UNIVERSAL && NUM2INT(tag) > 31)
ossl_raise(eASN1Error, "tag number for Universal too large");
ossl_asn1_set_tag(self, tag);
ossl_asn1_set_value(self, value);
@@ -760,7 +697,7 @@ static VALUE
join_der(VALUE enumerable)
{
VALUE str = rb_str_new(0, 0);
- rb_block_call(enumerable, rb_intern("each"), 0, 0, join_der_i, str);
+ rb_block_call(enumerable, id_each, 0, 0, join_der_i, str);
return str;
}
@@ -816,7 +753,7 @@ int_ossl_asn1_decode0_prim(unsigned char **pp, long length, long hlen, int tag,
p = *pp;
- if(tc == sUNIVERSAL && tag < ossl_asn1_info_size) {
+ if(tc == sym_UNIVERSAL && tag < ossl_asn1_info_size) {
switch(tag){
case V_ASN1_EOC:
value = decode_eoc(p, hlen+length);
@@ -858,13 +795,14 @@ int_ossl_asn1_decode0_prim(unsigned char **pp, long length, long hlen, int tag,
*pp += hlen + length;
*num_read = hlen + length;
- if (tc == sUNIVERSAL && tag < ossl_asn1_info_size && ossl_asn1_info[tag].klass) {
+ if (tc == sym_UNIVERSAL &&
+ tag < ossl_asn1_info_size && ossl_asn1_info[tag].klass) {
VALUE klass = *ossl_asn1_info[tag].klass;
VALUE args[4];
args[0] = value;
args[1] = INT2NUM(tag);
args[2] = Qnil;
- args[3] = ID2SYM(tc);
+ args[3] = tc;
asn1data = rb_obj_alloc(klass);
ossl_asn1_initialize(4, args, asn1data);
if(tag == V_ASN1_BIT_STRING){
@@ -873,7 +811,7 @@ int_ossl_asn1_decode0_prim(unsigned char **pp, long length, long hlen, int tag,
}
else {
asn1data = rb_obj_alloc(cASN1Data);
- ossl_asn1data_initialize(asn1data, value, INT2NUM(tag), ID2SYM(tc));
+ ossl_asn1data_initialize(asn1data, value, INT2NUM(tag), tc);
}
return asn1data;
@@ -886,28 +824,27 @@ int_ossl_asn1_decode0_cons(unsigned char **pp, long max_len, long length,
{
VALUE value, asn1data, ary;
int infinite;
- long off = *offset;
+ long available_len, off = *offset;
infinite = (j == 0x21);
ary = rb_ary_new();
- while (length > 0 || infinite) {
+ available_len = infinite ? max_len : length;
+ while (available_len > 0) {
long inner_read = 0;
- value = ossl_asn1_decode0(pp, max_len, &off, depth + 1, yield, &inner_read);
+ value = ossl_asn1_decode0(pp, available_len, &off, depth + 1, yield, &inner_read);
*num_read += inner_read;
- max_len -= inner_read;
+ available_len -= inner_read;
rb_ary_push(ary, value);
- if (length > 0)
- length -= inner_read;
if (infinite &&
NUM2INT(ossl_asn1_get_tag(value)) == V_ASN1_EOC &&
- SYM2ID(ossl_asn1_get_tag_class(value)) == sUNIVERSAL) {
+ ossl_asn1_get_tag_class(value) == sym_UNIVERSAL) {
break;
}
}
- if (tc == sUNIVERSAL) {
+ if (tc == sym_UNIVERSAL) {
VALUE args[4];
int not_sequence_or_set;
@@ -929,12 +866,12 @@ int_ossl_asn1_decode0_cons(unsigned char **pp, long max_len, long length,
args[0] = ary;
args[1] = INT2NUM(tag);
args[2] = Qnil;
- args[3] = ID2SYM(tc);
+ args[3] = tc;
ossl_asn1_initialize(4, args, asn1data);
}
else {
asn1data = rb_obj_alloc(cASN1Data);
- ossl_asn1data_initialize(asn1data, ary, INT2NUM(tag), ID2SYM(tc));
+ ossl_asn1data_initialize(asn1data, ary, INT2NUM(tag), tc);
}
if (infinite)
@@ -964,13 +901,13 @@ ossl_asn1_decode0(unsigned char **pp, long length, long *offset, int depth,
if(j & 0x80) ossl_raise(eASN1Error, NULL);
if(len > length) ossl_raise(eASN1Error, "value is too short");
if((tc & V_ASN1_PRIVATE) == V_ASN1_PRIVATE)
- tag_class = sPRIVATE;
+ tag_class = sym_PRIVATE;
else if((tc & V_ASN1_CONTEXT_SPECIFIC) == V_ASN1_CONTEXT_SPECIFIC)
- tag_class = sCONTEXT_SPECIFIC;
+ tag_class = sym_CONTEXT_SPECIFIC;
else if((tc & V_ASN1_APPLICATION) == V_ASN1_APPLICATION)
- tag_class = sAPPLICATION;
+ tag_class = sym_APPLICATION;
else
- tag_class = sUNIVERSAL;
+ tag_class = sym_UNIVERSAL;
hlen = p - start;
@@ -989,7 +926,7 @@ ossl_asn1_decode0(unsigned char **pp, long length, long *offset, int depth,
if(j & V_ASN1_CONSTRUCTED) {
*pp += hlen;
off += hlen;
- asn1data = int_ossl_asn1_decode0_cons(pp, length, len, &off, depth, yield, j, tag, tag_class, &inner_read);
+ asn1data = int_ossl_asn1_decode0_cons(pp, length - hlen, len, &off, depth, yield, j, tag, tag_class, &inner_read);
inner_read += hlen;
}
else {
@@ -1162,19 +1099,19 @@ ossl_asn1_initialize(int argc, VALUE *argv, VALUE self)
ossl_raise(eASN1Error, "invalid tagging method");
if(NIL_P(tag_class)) {
if (NIL_P(tagging))
- tag_class = ID2SYM(sUNIVERSAL);
+ tag_class = sym_UNIVERSAL;
else
- tag_class = ID2SYM(sCONTEXT_SPECIFIC);
+ tag_class = sym_CONTEXT_SPECIFIC;
}
if(!SYMBOL_P(tag_class))
ossl_raise(eASN1Error, "invalid tag class");
- if(!NIL_P(tagging) && SYM2ID(tagging) == sIMPLICIT && NUM2INT(tag) > 31)
+ if (tagging == sym_IMPLICIT && NUM2INT(tag) > 31)
ossl_raise(eASN1Error, "tag number for Universal too large");
}
else{
tag = INT2NUM(ossl_asn1_default_tag(self));
tagging = Qnil;
- tag_class = ID2SYM(sUNIVERSAL);
+ tag_class = sym_UNIVERSAL;
}
ossl_asn1_set_tag(self, tag);
ossl_asn1_set_value(self, value);
@@ -1190,7 +1127,7 @@ ossl_asn1eoc_initialize(VALUE self) {
VALUE tag, tagging, tag_class, value;
tag = INT2NUM(ossl_asn1_default_tag(self));
tagging = Qnil;
- tag_class = ID2SYM(sUNIVERSAL);
+ tag_class = sym_UNIVERSAL;
value = rb_str_new("", 0);
ossl_asn1_set_tag(self, tag);
ossl_asn1_set_value(self, value);
@@ -1264,8 +1201,8 @@ ossl_asn1cons_to_der(VALUE self)
if (inf_length == Qtrue) {
VALUE ary, example;
constructed = 2;
- if (CLASS_OF(self) == cASN1Sequence ||
- CLASS_OF(self) == cASN1Set) {
+ if (rb_obj_class(self) == cASN1Sequence ||
+ rb_obj_class(self) == cASN1Set) {
tag = ossl_asn1_default_tag(self);
}
else { /* must be a constructive encoding of a primitive value */
@@ -1294,7 +1231,7 @@ ossl_asn1cons_to_der(VALUE self)
}
}
else {
- if (CLASS_OF(self) == cASN1Constructive)
+ if (rb_obj_class(self) == cASN1Constructive)
ossl_raise(eASN1Error, "Constructive shall only be used with infinite length");
tag = ossl_asn1_default_tag(self);
}
@@ -1348,7 +1285,8 @@ ossl_asn1cons_to_der(VALUE self)
static VALUE
ossl_asn1cons_each(VALUE self)
{
- rb_ary_each(ossl_asn1_get_value(self));
+ rb_funcall(ossl_asn1_get_value(self), id_each, 0);
+
return self;
}
@@ -1476,12 +1414,12 @@ Init_ossl_asn1(void)
eOSSLError = rb_define_class_under(mOSSL, "OpenSSLError", rb_eStandardError);
#endif
- sUNIVERSAL = rb_intern("UNIVERSAL");
- sCONTEXT_SPECIFIC = rb_intern("CONTEXT_SPECIFIC");
- sAPPLICATION = rb_intern("APPLICATION");
- sPRIVATE = rb_intern("PRIVATE");
- sEXPLICIT = rb_intern("EXPLICIT");
- sIMPLICIT = rb_intern("IMPLICIT");
+ sym_UNIVERSAL = ID2SYM(rb_intern_const("UNIVERSAL"));
+ sym_CONTEXT_SPECIFIC = ID2SYM(rb_intern_const("CONTEXT_SPECIFIC"));
+ sym_APPLICATION = ID2SYM(rb_intern_const("APPLICATION"));
+ sym_PRIVATE = ID2SYM(rb_intern_const("PRIVATE"));
+ sym_EXPLICIT = ID2SYM(rb_intern_const("EXPLICIT"));
+ sym_IMPLICIT = ID2SYM(rb_intern_const("IMPLICIT"));
sivVALUE = rb_intern("@value");
sivTAG = rb_intern("@tag");
@@ -1989,4 +1927,6 @@ do{\
rb_hash_aset(class_tag_map, cASN1UniversalString, INT2NUM(V_ASN1_UNIVERSALSTRING));
rb_hash_aset(class_tag_map, cASN1BMPString, INT2NUM(V_ASN1_BMPSTRING));
rb_global_variable(&class_tag_map);
+
+ id_each = rb_intern_const("each");
}
diff --git a/ext/openssl/ossl_bio.c b/ext/openssl/ossl_bio.c
index feaf229..1609b09 100644
--- a/ext/openssl/ossl_bio.c
+++ b/ext/openssl/ossl_bio.c
@@ -8,9 +8,6 @@
* (See the file 'LICENCE'.)
*/
#include "ossl.h"
-#ifdef HAVE_UNISTD_H
-#include <unistd.h>
-#endif
BIO *
ossl_obj2bio(VALUE obj)
diff --git a/ext/openssl/ossl_bn.c b/ext/openssl/ossl_bn.c
index 19a868c..eaf6254 100644
--- a/ext/openssl/ossl_bn.c
+++ b/ext/openssl/ossl_bn.c
@@ -380,7 +380,7 @@ BIGNUM_BOOL1(is_odd)
BIGNUM *bn, *result; \
VALUE obj; \
GetBN(self, bn); \
- obj = NewBN(CLASS_OF(self)); \
+ obj = NewBN(rb_obj_class(self)); \
if (!(result = BN_new())) { \
ossl_raise(eBNError, NULL); \
} \
@@ -406,7 +406,7 @@ BIGNUM_1c(sqr)
BIGNUM *bn1, *bn2 = GetBNPtr(other), *result; \
VALUE obj; \
GetBN(self, bn1); \
- obj = NewBN(CLASS_OF(self)); \
+ obj = NewBN(rb_obj_class(self)); \
if (!(result = BN_new())) { \
ossl_raise(eBNError, NULL); \
} \
@@ -439,7 +439,7 @@ BIGNUM_2(sub)
BIGNUM *bn1, *bn2 = GetBNPtr(other), *result; \
VALUE obj; \
GetBN(self, bn1); \
- obj = NewBN(CLASS_OF(self)); \
+ obj = NewBN(rb_obj_class(self)); \
if (!(result = BN_new())) { \
ossl_raise(eBNError, NULL); \
} \
@@ -504,12 +504,13 @@ static VALUE
ossl_bn_div(VALUE self, VALUE other)
{
BIGNUM *bn1, *bn2 = GetBNPtr(other), *r1, *r2;
- VALUE obj1, obj2;
+ VALUE klass, obj1, obj2;
GetBN(self, bn1);
- obj1 = NewBN(CLASS_OF(self));
- obj2 = NewBN(CLASS_OF(self));
+ klass = rb_obj_class(self);
+ obj1 = NewBN(klass);
+ obj2 = NewBN(klass);
if (!(r1 = BN_new())) {
ossl_raise(eBNError, NULL);
}
@@ -536,7 +537,7 @@ ossl_bn_div(VALUE self, VALUE other)
BIGNUM *bn3 = GetBNPtr(other2), *result; \
VALUE obj; \
GetBN(self, bn1); \
- obj = NewBN(CLASS_OF(self)); \
+ obj = NewBN(rb_obj_class(self)); \
if (!(result = BN_new())) { \
ossl_raise(eBNError, NULL); \
} \
@@ -639,7 +640,7 @@ ossl_bn_is_bit_set(VALUE self, VALUE bit)
VALUE obj; \
b = NUM2INT(bits); \
GetBN(self, bn); \
- obj = NewBN(CLASS_OF(self)); \
+ obj = NewBN(rb_obj_class(self)); \
if (!(result = BN_new())) { \
ossl_raise(eBNError, NULL); \
} \
diff --git a/ext/openssl/ossl_cipher.c b/ext/openssl/ossl_cipher.c
index 57bc3cf..73b667b 100644
--- a/ext/openssl/ossl_cipher.c
+++ b/ext/openssl/ossl_cipher.c
@@ -36,7 +36,7 @@
*/
VALUE cCipher;
VALUE eCipherError;
-static ID id_auth_tag_len;
+static ID id_auth_tag_len, id_key_set;
static VALUE ossl_cipher_alloc(VALUE klass);
static void ossl_cipher_free(void *ptr);
@@ -118,7 +118,6 @@ ossl_cipher_initialize(VALUE self, VALUE str)
EVP_CIPHER_CTX *ctx;
const EVP_CIPHER *cipher;
char *name;
- unsigned char dummy_key[EVP_MAX_KEY_LENGTH] = { 0 };
name = StringValueCStr(str);
GetCipherInit(self, ctx);
@@ -129,16 +128,7 @@ ossl_cipher_initialize(VALUE self, VALUE str)
if (!(cipher = EVP_get_cipherbyname(name))) {
ossl_raise(rb_eRuntimeError, "unsupported cipher algorithm (%"PRIsVALUE")", str);
}
- /*
- * EVP_CipherInit_ex() allows to specify NULL to key and IV, however some
- * ciphers don't handle well (OpenSSL's bug). [Bug #2768]
- *
- * The EVP which has EVP_CIPH_RAND_KEY flag (such as DES3) allows
- * uninitialized key, but other EVPs (such as AES) does not allow it.
- * Calling EVP_CipherUpdate() without initializing key causes SEGV so we
- * set the data filled with "\0" as the key by default.
- */
- if (EVP_CipherInit_ex(ctx, cipher, NULL, dummy_key, NULL, -1) != 1)
+ if (EVP_CipherInit_ex(ctx, cipher, NULL, NULL, NULL, -1) != 1)
ossl_raise(eCipherError, NULL);
return self;
@@ -251,6 +241,9 @@ ossl_cipher_init(int argc, VALUE *argv, VALUE self, int mode)
ossl_raise(eCipherError, NULL);
}
+ if (p_key)
+ rb_ivar_set(self, id_key_set, Qtrue);
+
return self;
}
@@ -337,6 +330,8 @@ ossl_cipher_pkcs5_keyivgen(int argc, VALUE *argv, VALUE self)
OPENSSL_cleanse(key, sizeof key);
OPENSSL_cleanse(iv, sizeof iv);
+ rb_ivar_set(self, id_key_set, Qtrue);
+
return Qnil;
}
@@ -387,6 +382,9 @@ ossl_cipher_update(int argc, VALUE *argv, VALUE self)
rb_scan_args(argc, argv, "11", &data, &str);
+ if (!RTEST(rb_attr_get(self, id_key_set)))
+ ossl_raise(eCipherError, "key not set");
+
StringValue(data);
in = (unsigned char *)RSTRING_PTR(data);
if ((in_len = RSTRING_LEN(data)) == 0)
@@ -488,6 +486,8 @@ ossl_cipher_set_key(VALUE self, VALUE key)
if (EVP_CipherInit_ex(ctx, NULL, NULL, (unsigned char *)RSTRING_PTR(key), NULL, -1) != 1)
ossl_raise(eCipherError, NULL);
+ rb_ivar_set(self, id_key_set, Qtrue);
+
return key;
}
@@ -502,9 +502,6 @@ ossl_cipher_set_key(VALUE self, VALUE key)
* Cipher#random_iv to create a secure random IV.
*
* Only call this method after calling Cipher#encrypt or Cipher#decrypt.
- *
- * If not explicitly set, the OpenSSL default of an all-zeroes ("\\0") IV is
- * used.
*/
static VALUE
ossl_cipher_set_iv(VALUE self, VALUE iv)
@@ -530,6 +527,27 @@ ossl_cipher_set_iv(VALUE self, VALUE iv)
return iv;
}
+/*
+ * call-seq:
+ * cipher.authenticated? -> true | false
+ *
+ * Indicated whether this Cipher instance uses an Authenticated Encryption
+ * mode.
+ */
+static VALUE
+ossl_cipher_is_authenticated(VALUE self)
+{
+ EVP_CIPHER_CTX *ctx;
+
+ GetCipher(self, ctx);
+
+#if defined(HAVE_AUTHENTICATED_ENCRYPTION)
+ return (EVP_CIPHER_CTX_flags(ctx) & EVP_CIPH_FLAG_AEAD_CIPHER) ? Qtrue : Qfalse;
+#else
+ return Qfalse;
+#endif
+}
+
#ifdef HAVE_AUTHENTICATED_ENCRYPTION
/*
* call-seq:
@@ -676,23 +694,6 @@ ossl_cipher_set_auth_tag_len(VALUE self, VALUE vlen)
}
/*
- * call-seq:
- * cipher.authenticated? -> boolean
- *
- * Indicated whether this Cipher instance uses an Authenticated Encryption
- * mode.
- */
-static VALUE
-ossl_cipher_is_authenticated(VALUE self)
-{
- EVP_CIPHER_CTX *ctx;
-
- GetCipher(self, ctx);
-
- return (EVP_CIPHER_CTX_flags(ctx) & EVP_CIPH_FLAG_AEAD_CIPHER) ? Qtrue : Qfalse;
-}
-
-/*
* call-seq:
* cipher.iv_len = integer -> integer
*
@@ -726,7 +727,6 @@ ossl_cipher_set_iv_length(VALUE self, VALUE iv_length)
#define ossl_cipher_get_auth_tag rb_f_notimplement
#define ossl_cipher_set_auth_tag rb_f_notimplement
#define ossl_cipher_set_auth_tag_len rb_f_notimplement
-#define ossl_cipher_is_authenticated rb_f_notimplement
#define ossl_cipher_set_iv_length rb_f_notimplement
#endif
@@ -939,12 +939,10 @@ Init_ossl_cipher(void)
* you absolutely need it</b>
*
* Because of this, you will end up with a mode that explicitly requires
- * an IV in any case. Note that for backwards compatibility reasons,
- * setting an IV is not explicitly mandated by the Cipher API. If not
- * set, OpenSSL itself defaults to an all-zeroes IV ("\\0", not the
- * character). Although the IV can be seen as public information, i.e.
- * it may be transmitted in public once generated, it should still stay
- * unpredictable to prevent certain kinds of attacks. Therefore, ideally
+ * an IV in any case. Although the IV can be seen as public information,
+ * i.e. it may be transmitted in public once generated, it should still
+ * stay unpredictable to prevent certain kinds of attacks. Therefore,
+ * ideally
*
* <b>Always create a secure random IV for every encryption of your
* Cipher</b>
@@ -1082,4 +1080,5 @@ Init_ossl_cipher(void)
rb_define_method(cCipher, "padding=", ossl_cipher_set_padding, 1);
id_auth_tag_len = rb_intern_const("auth_tag_len");
+ id_key_set = rb_intern_const("key_set");
}
diff --git a/ext/openssl/ossl_digest.c b/ext/openssl/ossl_digest.c
index 44d9618..fdafda0 100644
--- a/ext/openssl/ossl_digest.c
+++ b/ext/openssl/ossl_digest.c
@@ -80,10 +80,13 @@ ossl_digest_new(const EVP_MD *md)
EVP_MD_CTX *ctx;
ret = ossl_digest_alloc(cDigest);
- GetDigest(ret, ctx);
- if (EVP_DigestInit_ex(ctx, md, NULL) != 1) {
- ossl_raise(eDigestError, "Digest initialization failed.");
- }
+ ctx = EVP_MD_CTX_new();
+ if (!ctx)
+ ossl_raise(eDigestError, "EVP_MD_CTX_new");
+ RTYPEDDATA_DATA(ret) = ctx;
+
+ if (!EVP_DigestInit_ex(ctx, md, NULL))
+ ossl_raise(eDigestError, "Digest initialization failed");
return ret;
}
@@ -94,13 +97,7 @@ ossl_digest_new(const EVP_MD *md)
static VALUE
ossl_digest_alloc(VALUE klass)
{
- VALUE obj = TypedData_Wrap_Struct(klass, &ossl_digest_type, 0);
- EVP_MD_CTX *ctx = EVP_MD_CTX_create();
- if (ctx == NULL)
- ossl_raise(rb_eRuntimeError, "EVP_MD_CTX_create() failed");
- RTYPEDDATA_DATA(obj) = ctx;
-
- return obj;
+ return TypedData_Wrap_Struct(klass, &ossl_digest_type, 0);
}
VALUE ossl_digest_update(VALUE, VALUE);
@@ -133,11 +130,16 @@ ossl_digest_initialize(int argc, VALUE *argv, VALUE self)
md = GetDigestPtr(type);
if (!NIL_P(data)) StringValue(data);
- GetDigest(self, ctx);
- if (EVP_DigestInit_ex(ctx, md, NULL) != 1) {
- ossl_raise(eDigestError, "Digest initialization failed.");
+ TypedData_Get_Struct(self, EVP_MD_CTX, &ossl_digest_type, ctx);
+ if (!ctx) {
+ RTYPEDDATA_DATA(self) = ctx = EVP_MD_CTX_new();
+ if (!ctx)
+ ossl_raise(eDigestError, "EVP_MD_CTX_new");
}
+ if (!EVP_DigestInit_ex(ctx, md, NULL))
+ ossl_raise(eDigestError, "Digest initialization failed");
+
if (!NIL_P(data)) return ossl_digest_update(self, data);
return self;
}
@@ -150,7 +152,12 @@ ossl_digest_copy(VALUE self, VALUE other)
rb_check_frozen(self);
if (self == other) return self;
- GetDigest(self, ctx1);
+ TypedData_Get_Struct(self, EVP_MD_CTX, &ossl_digest_type, ctx1);
+ if (!ctx1) {
+ RTYPEDDATA_DATA(self) = ctx1 = EVP_MD_CTX_new();
+ if (!ctx1)
+ ossl_raise(eDigestError, "EVP_MD_CTX_new");
+ }
SafeGetDigest(other, ctx2);
if (!EVP_MD_CTX_copy(ctx1, ctx2)) {
diff --git a/ext/openssl/ossl_engine.c b/ext/openssl/ossl_engine.c
index f4863b3..e73bfb3 100644
--- a/ext/openssl/ossl_engine.c
+++ b/ext/openssl/ossl_engine.c
@@ -227,21 +227,6 @@ ossl_engine_s_by_id(VALUE klass, VALUE id)
return obj;
}
-static VALUE
-ossl_engine_s_alloc(VALUE klass)
-{
- ENGINE *e;
- VALUE obj;
-
- obj = NewEngine(klass);
- if (!(e = ENGINE_new())) {
- ossl_raise(eEngineError, NULL);
- }
- SetEngine(obj, e);
-
- return obj;
-}
-
/* Document-method: OpenSSL::Engine#id
*
* Get the id for this engine
@@ -537,13 +522,11 @@ Init_ossl_engine(void)
cEngine = rb_define_class_under(mOSSL, "Engine", rb_cObject);
eEngineError = rb_define_class_under(cEngine, "EngineError", eOSSLError);
- rb_define_alloc_func(cEngine, ossl_engine_s_alloc);
+ rb_undef_alloc_func(cEngine);
rb_define_singleton_method(cEngine, "load", ossl_engine_s_load, -1);
rb_define_singleton_method(cEngine, "cleanup", ossl_engine_s_cleanup, 0);
rb_define_singleton_method(cEngine, "engines", ossl_engine_s_engines, 0);
rb_define_singleton_method(cEngine, "by_id", ossl_engine_s_by_id, 1);
- rb_undef_method(CLASS_OF(cEngine), "new");
- rb_undef_method(cEngine, "initialize_copy");
rb_define_method(cEngine, "id", ossl_engine_get_id, 0);
rb_define_method(cEngine, "name", ossl_engine_get_name, 0);
diff --git a/ext/openssl/ossl_ns_spki.c b/ext/openssl/ossl_ns_spki.c
index 2f7845b..98f6552 100644
--- a/ext/openssl/ossl_ns_spki.c
+++ b/ext/openssl/ossl_ns_spki.c
@@ -159,8 +159,6 @@ ossl_spki_print(VALUE self)
{
NETSCAPE_SPKI *spki;
BIO *out;
- BUF_MEM *buf;
- VALUE str;
GetSPKI(self, spki);
if (!(out = BIO_new(BIO_s_mem()))) {
@@ -170,11 +168,8 @@ ossl_spki_print(VALUE self)
BIO_free(out);
ossl_raise(eSPKIError, NULL);
}
- BIO_get_mem_ptr(out, &buf);
- str = rb_str_new(buf->data, buf->length);
- BIO_free(out);
- return str;
+ return ossl_membio2str(out);
}
/*
diff --git a/ext/openssl/ossl_pkcs7.c b/ext/openssl/ossl_pkcs7.c
index fd58b48..4040355 100644
--- a/ext/openssl/ossl_pkcs7.c
+++ b/ext/openssl/ossl_pkcs7.c
@@ -795,7 +795,7 @@ ossl_pkcs7_verify(int argc, VALUE *argv, VALUE self)
BIO_free(in);
sk_X509_pop_free(x509s, X509_free);
if (ok < 0) ossl_raise(ePKCS7Error, "PKCS7_verify");
- msg = ERR_reason_error_string(ERR_get_error());
+ msg = ERR_reason_error_string(ERR_peek_error());
ossl_pkcs7_set_err_string(self, msg ? rb_str_new2(msg) : Qnil);
ossl_clear_error();
data = ossl_membio2str(out);
diff --git a/ext/openssl/ossl_pkey.c b/ext/openssl/ossl_pkey.c
index 3c7c5e1..9e6c615 100644
--- a/ext/openssl/ossl_pkey.c
+++ b/ext/openssl/ossl_pkey.c
@@ -70,12 +70,12 @@ const rb_data_type_t ossl_evp_pkey_type = {
0, 0, RUBY_TYPED_FREE_IMMEDIATELY,
};
-VALUE
-ossl_pkey_new(EVP_PKEY *pkey)
+static VALUE
+pkey_new0(EVP_PKEY *pkey)
{
- if (!pkey) {
- ossl_raise(ePKeyError, "Cannot make new key from NULL.");
- }
+ if (!pkey)
+ ossl_raise(ePKeyError, "cannot make new key from NULL");
+
switch (EVP_PKEY_base_id(pkey)) {
#if !defined(OPENSSL_NO_RSA)
case EVP_PKEY_RSA:
@@ -96,29 +96,21 @@ ossl_pkey_new(EVP_PKEY *pkey)
default:
ossl_raise(ePKeyError, "unsupported key type");
}
-
- UNREACHABLE;
}
VALUE
-ossl_pkey_new_from_file(VALUE filename)
+ossl_pkey_new(EVP_PKEY *pkey)
{
- FILE *fp;
- EVP_PKEY *pkey;
-
- rb_check_safe_obj(filename);
- if (!(fp = fopen(StringValueCStr(filename), "r"))) {
- ossl_raise(ePKeyError, "%s", strerror(errno));
- }
- rb_fd_fix_cloexec(fileno(fp));
+ VALUE obj;
+ int status;
- pkey = PEM_read_PrivateKey(fp, NULL, ossl_pem_passwd_cb, NULL);
- fclose(fp);
- if (!pkey) {
- ossl_raise(ePKeyError, NULL);
+ obj = rb_protect((VALUE (*)(VALUE))pkey_new0, (VALUE)pkey, &status);
+ if (status) {
+ EVP_PKEY_free(pkey);
+ rb_jump_tag(status);
}
- return ossl_pkey_new(pkey);
+ return obj;
}
/*
@@ -166,6 +158,45 @@ ossl_pkey_new_from_data(int argc, VALUE *argv, VALUE self)
return ossl_pkey_new(pkey);
}
+static void
+pkey_check_public_key(EVP_PKEY *pkey)
+{
+ void *ptr;
+ const BIGNUM *n, *e, *pubkey;
+
+ if (EVP_PKEY_missing_parameters(pkey))
+ ossl_raise(ePKeyError, "parameters missing");
+
+ ptr = EVP_PKEY_get0(pkey);
+ switch (EVP_PKEY_base_id(pkey)) {
+ case EVP_PKEY_RSA:
+ RSA_get0_key(ptr, &n, &e, NULL);
+ if (n && e)
+ return;
+ break;
+ case EVP_PKEY_DSA:
+ DSA_get0_key(ptr, &pubkey, NULL);
+ if (pubkey)
+ return;
+ break;
+ case EVP_PKEY_DH:
+ DH_get0_key(ptr, &pubkey, NULL);
+ if (pubkey)
+ return;
+ break;
+#if !defined(OPENSSL_NO_EC)
+ case EVP_PKEY_EC:
+ if (EC_KEY_get0_public_key(ptr))
+ return;
+ break;
+#endif
+ default:
+ /* unsupported type; assuming ok */
+ return;
+ }
+ ossl_raise(ePKeyError, "public key missing");
+}
+
EVP_PKEY *
GetPKeyPtr(VALUE obj)
{
@@ -264,18 +295,23 @@ ossl_pkey_sign(VALUE self, VALUE digest, VALUE data)
pkey = GetPrivPKeyPtr(self);
md = GetDigestPtr(digest);
StringValue(data);
- str = rb_str_new(0, EVP_PKEY_size(pkey)+16);
+ str = rb_str_new(0, EVP_PKEY_size(pkey));
ctx = EVP_MD_CTX_new();
if (!ctx)
ossl_raise(ePKeyError, "EVP_MD_CTX_new");
- EVP_SignInit(ctx, md);
- EVP_SignUpdate(ctx, RSTRING_PTR(data), RSTRING_LEN(data));
+ if (!EVP_SignInit_ex(ctx, md, NULL)) {
+ EVP_MD_CTX_free(ctx);
+ ossl_raise(ePKeyError, "EVP_SignInit_ex");
+ }
+ if (!EVP_SignUpdate(ctx, RSTRING_PTR(data), RSTRING_LEN(data))) {
+ EVP_MD_CTX_free(ctx);
+ ossl_raise(ePKeyError, "EVP_SignUpdate");
+ }
result = EVP_SignFinal(ctx, (unsigned char *)RSTRING_PTR(str), &buf_len, pkey);
EVP_MD_CTX_free(ctx);
if (!result)
- ossl_raise(ePKeyError, NULL);
- assert((long)buf_len <= RSTRING_LEN(str));
+ ossl_raise(ePKeyError, "EVP_SignFinal");
rb_str_set_len(str, buf_len);
return str;
@@ -308,19 +344,27 @@ ossl_pkey_verify(VALUE self, VALUE digest, VALUE sig, VALUE data)
EVP_PKEY *pkey;
const EVP_MD *md;
EVP_MD_CTX *ctx;
- int result;
+ int siglen, result;
GetPKey(self, pkey);
+ pkey_check_public_key(pkey);
md = GetDigestPtr(digest);
StringValue(sig);
+ siglen = RSTRING_LENINT(sig);
StringValue(data);
ctx = EVP_MD_CTX_new();
if (!ctx)
ossl_raise(ePKeyError, "EVP_MD_CTX_new");
- EVP_VerifyInit(ctx, md);
- EVP_VerifyUpdate(ctx, RSTRING_PTR(data), RSTRING_LEN(data));
- result = EVP_VerifyFinal(ctx, (unsigned char *)RSTRING_PTR(sig), RSTRING_LENINT(sig), pkey);
+ if (!EVP_VerifyInit_ex(ctx, md, NULL)) {
+ EVP_MD_CTX_free(ctx);
+ ossl_raise(ePKeyError, "EVP_VerifyInit_ex");
+ }
+ if (!EVP_VerifyUpdate(ctx, RSTRING_PTR(data), RSTRING_LEN(data))) {
+ EVP_MD_CTX_free(ctx);
+ ossl_raise(ePKeyError, "EVP_VerifyUpdate");
+ }
+ result = EVP_VerifyFinal(ctx, (unsigned char *)RSTRING_PTR(sig), siglen, pkey);
EVP_MD_CTX_free(ctx);
switch (result) {
case 0:
@@ -329,9 +373,8 @@ ossl_pkey_verify(VALUE self, VALUE digest, VALUE sig, VALUE data)
case 1:
return Qtrue;
default:
- ossl_raise(ePKeyError, NULL);
+ ossl_raise(ePKeyError, "EVP_VerifyFinal");
}
- return Qnil; /* dummy */
}
/*
diff --git a/ext/openssl/ossl_pkey.h b/ext/openssl/ossl_pkey.h
index 218f2eb..e3b723c 100644
--- a/ext/openssl/ossl_pkey.h
+++ b/ext/openssl/ossl_pkey.h
@@ -48,7 +48,6 @@ int ossl_generate_cb_2(int p, int n, BN_GENCB *cb);
void ossl_generate_cb_stop(void *ptr);
VALUE ossl_pkey_new(EVP_PKEY *);
-VALUE ossl_pkey_new_from_file(VALUE);
EVP_PKEY *GetPKeyPtr(VALUE);
EVP_PKEY *DupPKeyPtr(VALUE);
EVP_PKEY *GetPrivPKeyPtr(VALUE);
diff --git a/ext/openssl/ossl_pkey_dh.c b/ext/openssl/ossl_pkey_dh.c
index 938efe1..dd85b7b 100644
--- a/ext/openssl/ossl_pkey_dh.c
+++ b/ext/openssl/ossl_pkey_dh.c
@@ -460,7 +460,7 @@ ossl_dh_to_public_key(VALUE self)
GetDH(self, orig_dh);
dh = DHparams_dup(orig_dh); /* err check perfomed by dh_instance */
- obj = dh_instance(CLASS_OF(self), dh);
+ obj = dh_instance(rb_obj_class(self), dh);
if (obj == Qfalse) {
DH_free(dh);
ossl_raise(eDHError, NULL);
diff --git a/ext/openssl/ossl_pkey_dsa.c b/ext/openssl/ossl_pkey_dsa.c
index 3821cd8..8508541 100644
--- a/ext/openssl/ossl_pkey_dsa.c
+++ b/ext/openssl/ossl_pkey_dsa.c
@@ -491,7 +491,7 @@ ossl_dsa_to_public_key(VALUE self)
(i2d_of_void *)i2d_DSAPublicKey, (d2i_of_void *)d2i_DSAPublicKey, (char *)(dsa))
dsa = DSAPublicKey_dup(EVP_PKEY_get0_DSA(pkey));
#undef DSAPublicKey_dup
- obj = dsa_instance(CLASS_OF(self), dsa);
+ obj = dsa_instance(rb_obj_class(self), dsa);
if (obj == Qfalse) {
DSA_free(dsa);
ossl_raise(eDSAError, NULL);
@@ -499,8 +499,6 @@ ossl_dsa_to_public_key(VALUE self)
return obj;
}
-#define ossl_dsa_buf_size(dsa) (DSA_size(dsa) + 16)
-
/*
* call-seq:
* dsa.syssign(string) -> aString
@@ -535,7 +533,7 @@ ossl_dsa_sign(VALUE self, VALUE data)
if (!DSA_PRIVATE(self, dsa))
ossl_raise(eDSAError, "Private DSA key needed!");
StringValue(data);
- str = rb_str_new(0, ossl_dsa_buf_size(dsa));
+ str = rb_str_new(0, DSA_size(dsa));
if (!DSA_sign(0, (unsigned char *)RSTRING_PTR(data), RSTRING_LENINT(data),
(unsigned char *)RSTRING_PTR(str),
&buf_len, dsa)) { /* type is ignored (0) */
diff --git a/ext/openssl/ossl_pkey_ec.c b/ext/openssl/ossl_pkey_ec.c
index 20a7222..5191c0f 100644
--- a/ext/openssl/ossl_pkey_ec.c
+++ b/ext/openssl/ossl_pkey_ec.c
@@ -643,11 +643,10 @@ static VALUE ossl_ec_key_dsa_sign_asn1(VALUE self, VALUE data)
if (EC_KEY_get0_private_key(ec) == NULL)
ossl_raise(eECError, "Private EC key needed!");
- str = rb_str_new(0, ECDSA_size(ec) + 16);
+ str = rb_str_new(0, ECDSA_size(ec));
if (ECDSA_sign(0, (unsigned char *) RSTRING_PTR(data), RSTRING_LENINT(data), (unsigned char *) RSTRING_PTR(str), &buf_len, ec) != 1)
- ossl_raise(eECError, "ECDSA_sign");
-
- rb_str_resize(str, buf_len);
+ ossl_raise(eECError, "ECDSA_sign");
+ rb_str_set_len(str, buf_len);
return str;
}
@@ -1106,6 +1105,22 @@ static VALUE ossl_ec_group_get_point_conversion_form(VALUE self)
return ID2SYM(ret);
}
+static point_conversion_form_t
+parse_point_conversion_form_symbol(VALUE sym)
+{
+ ID id = SYM2ID(sym);
+
+ if (id == ID_uncompressed)
+ return POINT_CONVERSION_UNCOMPRESSED;
+ else if (id == ID_compressed)
+ return POINT_CONVERSION_COMPRESSED;
+ else if (id == ID_hybrid)
+ return POINT_CONVERSION_HYBRID;
+ else
+ ossl_raise(rb_eArgError, "unsupported point conversion form %+"PRIsVALUE
+ " (expected :compressed, :uncompressed, or :hybrid)", sym);
+}
+
/*
* call-seq:
* group.point_conversion_form = form
@@ -1125,23 +1140,14 @@ static VALUE ossl_ec_group_get_point_conversion_form(VALUE self)
*
* See the OpenSSL documentation for EC_GROUP_set_point_conversion_form()
*/
-static VALUE ossl_ec_group_set_point_conversion_form(VALUE self, VALUE form_v)
+static VALUE
+ossl_ec_group_set_point_conversion_form(VALUE self, VALUE form_v)
{
- EC_GROUP *group = NULL;
+ EC_GROUP *group;
point_conversion_form_t form;
- ID form_id = SYM2ID(form_v);
GetECGroup(self, group);
-
- if (form_id == ID_uncompressed) {
- form = POINT_CONVERSION_UNCOMPRESSED;
- } else if (form_id == ID_compressed) {
- form = POINT_CONVERSION_COMPRESSED;
- } else if (form_id == ID_hybrid) {
- form = POINT_CONVERSION_HYBRID;
- } else {
- ossl_raise(rb_eArgError, "form must be :compressed, :uncompressed, or :hybrid");
- }
+ form = parse_point_conversion_form_symbol(form_v);
EC_GROUP_set_point_conversion_form(group, form);
@@ -1549,22 +1555,30 @@ static VALUE ossl_ec_point_set_to_infinity(VALUE self)
/*
* call-seq:
- * point.to_bn => OpenSSL::BN
+ * point.to_bn(conversion_form = nil) => OpenSSL::BN
+ *
+ * Convert the EC point into an octet string and store in an OpenSSL::BN. If
+ * +conversion_form+ is given, the point data is converted using the specified
+ * form. If not given, the default form set in the EC::Group object is used.
*
- * See the OpenSSL documentation for EC_POINT_point2bn()
+ * See also EC::Point#point_conversion_form=.
*/
-static VALUE ossl_ec_point_to_bn(VALUE self)
+static VALUE
+ossl_ec_point_to_bn(int argc, VALUE *argv, VALUE self)
{
EC_POINT *point;
- VALUE bn_obj;
+ VALUE form_obj, bn_obj;
const EC_GROUP *group;
point_conversion_form_t form;
BIGNUM *bn;
GetECPoint(self, point);
GetECPointGroup(self, group);
-
- form = EC_GROUP_get_point_conversion_form(group);
+ rb_scan_args(argc, argv, "01", &form_obj);
+ if (NIL_P(form_obj))
+ form = EC_GROUP_get_point_conversion_form(group);
+ else
+ form = parse_point_conversion_form_symbol(form_obj);
bn_obj = rb_obj_alloc(cBN);
bn = GetBNPtr(bn_obj);
@@ -1793,7 +1807,7 @@ void Init_ossl_ec(void)
rb_define_method(cEC_POINT, "set_to_infinity!", ossl_ec_point_set_to_infinity, 0);
/* all the other methods */
- rb_define_method(cEC_POINT, "to_bn", ossl_ec_point_to_bn, 0);
+ rb_define_method(cEC_POINT, "to_bn", ossl_ec_point_to_bn, -1);
rb_define_method(cEC_POINT, "mul", ossl_ec_point_mul, -1);
id_i_group = rb_intern("@group");
diff --git a/ext/openssl/ossl_pkey_rsa.c b/ext/openssl/ossl_pkey_rsa.c
index 17a7494..cea228d 100644
--- a/ext/openssl/ossl_pkey_rsa.c
+++ b/ext/openssl/ossl_pkey_rsa.c
@@ -404,8 +404,6 @@ ossl_rsa_to_der(VALUE self)
return str;
}
-#define ossl_rsa_buf_size(rsa) (RSA_size(rsa)+16)
-
/*
* call-seq:
* rsa.public_encrypt(string) => String
@@ -429,7 +427,7 @@ ossl_rsa_public_encrypt(int argc, VALUE *argv, VALUE self)
rb_scan_args(argc, argv, "11", &buffer, &padding);
pad = (argc == 1) ? RSA_PKCS1_PADDING : NUM2INT(padding);
StringValue(buffer);
- str = rb_str_new(0, ossl_rsa_buf_size(rsa));
+ str = rb_str_new(0, RSA_size(rsa));
buf_len = RSA_public_encrypt(RSTRING_LENINT(buffer), (unsigned char *)RSTRING_PTR(buffer),
(unsigned char *)RSTRING_PTR(str), rsa, pad);
if (buf_len < 0) ossl_raise(eRSAError, NULL);
@@ -461,7 +459,7 @@ ossl_rsa_public_decrypt(int argc, VALUE *argv, VALUE self)
rb_scan_args(argc, argv, "11", &buffer, &padding);
pad = (argc == 1) ? RSA_PKCS1_PADDING : NUM2INT(padding);
StringValue(buffer);
- str = rb_str_new(0, ossl_rsa_buf_size(rsa));
+ str = rb_str_new(0, RSA_size(rsa));
buf_len = RSA_public_decrypt(RSTRING_LENINT(buffer), (unsigned char *)RSTRING_PTR(buffer),
(unsigned char *)RSTRING_PTR(str), rsa, pad);
if (buf_len < 0) ossl_raise(eRSAError, NULL);
@@ -495,7 +493,7 @@ ossl_rsa_private_encrypt(int argc, VALUE *argv, VALUE self)
rb_scan_args(argc, argv, "11", &buffer, &padding);
pad = (argc == 1) ? RSA_PKCS1_PADDING : NUM2INT(padding);
StringValue(buffer);
- str = rb_str_new(0, ossl_rsa_buf_size(rsa));
+ str = rb_str_new(0, RSA_size(rsa));
buf_len = RSA_private_encrypt(RSTRING_LENINT(buffer), (unsigned char *)RSTRING_PTR(buffer),
(unsigned char *)RSTRING_PTR(str), rsa, pad);
if (buf_len < 0) ossl_raise(eRSAError, NULL);
@@ -529,7 +527,7 @@ ossl_rsa_private_decrypt(int argc, VALUE *argv, VALUE self)
rb_scan_args(argc, argv, "11", &buffer, &padding);
pad = (argc == 1) ? RSA_PKCS1_PADDING : NUM2INT(padding);
StringValue(buffer);
- str = rb_str_new(0, ossl_rsa_buf_size(rsa));
+ str = rb_str_new(0, RSA_size(rsa));
buf_len = RSA_private_decrypt(RSTRING_LENINT(buffer), (unsigned char *)RSTRING_PTR(buffer),
(unsigned char *)RSTRING_PTR(str), rsa, pad);
if (buf_len < 0) ossl_raise(eRSAError, NULL);
@@ -620,7 +618,7 @@ ossl_rsa_to_public_key(VALUE self)
GetPKeyRSA(self, pkey);
/* err check performed by rsa_instance */
rsa = RSAPublicKey_dup(EVP_PKEY_get0_RSA(pkey));
- obj = rsa_instance(CLASS_OF(self), rsa);
+ obj = rsa_instance(rb_obj_class(self), rsa);
if (obj == Qfalse) {
RSA_free(rsa);
ossl_raise(eRSAError, NULL);
diff --git a/ext/openssl/ossl_ssl.c b/ext/openssl/ossl_ssl.c
index 861f820..609ffdc 100644
--- a/ext/openssl/ossl_ssl.c
+++ b/ext/openssl/ossl_ssl.c
@@ -11,10 +11,6 @@
*/
#include "ossl.h"
-#if defined(HAVE_UNISTD_H)
-# include <unistd.h> /* for read(), and write() */
-#endif
-
#define numberof(ary) (int)(sizeof(ary)/sizeof((ary)[0]))
#ifdef _WIN32
@@ -36,7 +32,7 @@ VALUE cSSLSocket;
static VALUE eSSLErrorWaitReadable;
static VALUE eSSLErrorWaitWritable;
-static ID ID_callback_state;
+static ID ID_callback_state, id_tmp_dh_callback, id_tmp_ecdh_callback;
static VALUE sym_exception, sym_wait_readable, sym_wait_writable;
static ID id_i_cert_store, id_i_ca_file, id_i_ca_path, id_i_verify_mode,
@@ -223,69 +219,90 @@ ossl_client_cert_cb(SSL *ssl, X509 **x509, EVP_PKEY **pkey)
return 1;
}
-#if !defined(OPENSSL_NO_DH)
-static VALUE
-ossl_call_tmp_dh_callback(VALUE args)
+#if !defined(OPENSSL_NO_DH) || \
+ !defined(OPENSSL_NO_EC) && defined(HAVE_SSL_CTX_SET_TMP_ECDH_CALLBACK)
+struct tmp_dh_callback_args {
+ VALUE ssl_obj;
+ ID id;
+ int type;
+ int is_export;
+ int keylength;
+};
+
+static EVP_PKEY *
+ossl_call_tmp_dh_callback(struct tmp_dh_callback_args *args)
{
VALUE cb, dh;
EVP_PKEY *pkey;
- cb = rb_funcall(rb_ary_entry(args, 0), rb_intern("tmp_dh_callback"), 0);
-
- if (NIL_P(cb)) return Qfalse;
- dh = rb_apply(cb, rb_intern("call"), args);
+ cb = rb_funcall(args->ssl_obj, args->id, 0);
+ if (NIL_P(cb))
+ return NULL;
+ dh = rb_funcall(cb, rb_intern("call"), 3,
+ args->ssl_obj, INT2NUM(args->is_export), INT2NUM(args->keylength));
pkey = GetPKeyPtr(dh);
- if (EVP_PKEY_base_id(pkey) != EVP_PKEY_DH) return Qfalse;
+ if (EVP_PKEY_base_id(pkey) != args->type)
+ return NULL;
- return dh;
+ return pkey;
}
+#endif
-static DH*
+#if !defined(OPENSSL_NO_DH)
+static DH *
ossl_tmp_dh_callback(SSL *ssl, int is_export, int keylength)
{
- VALUE args, dh, rb_ssl;
+ VALUE rb_ssl;
+ EVP_PKEY *pkey;
+ struct tmp_dh_callback_args args;
+ int state;
rb_ssl = (VALUE)SSL_get_ex_data(ssl, ossl_ssl_ex_ptr_idx);
+ args.ssl_obj = rb_ssl;
+ args.id = id_tmp_dh_callback;
+ args.is_export = is_export;
+ args.keylength = keylength;
+ args.type = EVP_PKEY_DH;
+
+ pkey = (EVP_PKEY *)rb_protect((VALUE (*)(VALUE))ossl_call_tmp_dh_callback,
+ (VALUE)&args, &state);
+ if (state) {
+ rb_ivar_set(rb_ssl, ID_callback_state, INT2NUM(state));
+ return NULL;
+ }
+ if (!pkey)
+ return NULL;
- args = rb_ary_new_from_args(3, rb_ssl, INT2NUM(is_export), INT2NUM(keylength));
-
- dh = rb_protect(ossl_call_tmp_dh_callback, args, NULL);
- if (!RTEST(dh)) return NULL;
-
- return EVP_PKEY_get0_DH(GetPKeyPtr(dh));
+ return EVP_PKEY_get0_DH(pkey);
}
#endif /* OPENSSL_NO_DH */
#if !defined(OPENSSL_NO_EC) && defined(HAVE_SSL_CTX_SET_TMP_ECDH_CALLBACK)
-static VALUE
-ossl_call_tmp_ecdh_callback(VALUE args)
-{
- VALUE cb, ecdh;
- EVP_PKEY *pkey;
-
- cb = rb_funcall(rb_ary_entry(args, 0), rb_intern("tmp_ecdh_callback"), 0);
-
- if (NIL_P(cb)) return Qfalse;
- ecdh = rb_apply(cb, rb_intern("call"), args);
- pkey = GetPKeyPtr(ecdh);
- if (EVP_PKEY_base_id(pkey) != EVP_PKEY_EC) return Qfalse;
-
- return ecdh;
-}
-
-static EC_KEY*
+static EC_KEY *
ossl_tmp_ecdh_callback(SSL *ssl, int is_export, int keylength)
{
- VALUE args, ecdh, rb_ssl;
+ VALUE rb_ssl;
+ EVP_PKEY *pkey;
+ struct tmp_dh_callback_args args;
+ int state;
rb_ssl = (VALUE)SSL_get_ex_data(ssl, ossl_ssl_ex_ptr_idx);
+ args.ssl_obj = rb_ssl;
+ args.id = id_tmp_ecdh_callback;
+ args.is_export = is_export;
+ args.keylength = keylength;
+ args.type = EVP_PKEY_EC;
+
+ pkey = (EVP_PKEY *)rb_protect((VALUE (*)(VALUE))ossl_call_tmp_dh_callback,
+ (VALUE)&args, &state);
+ if (state) {
+ rb_ivar_set(rb_ssl, ID_callback_state, INT2NUM(state));
+ return NULL;
+ }
+ if (!pkey)
+ return NULL;
- args = rb_ary_new_from_args(3, rb_ssl, INT2NUM(is_export), INT2NUM(keylength));
-
- ecdh = rb_protect(ossl_call_tmp_ecdh_callback, args, NULL);
- if (!RTEST(ecdh)) return NULL;
-
- return EVP_PKEY_get0_EC_KEY(GetPKeyPtr(ecdh));
+ return EVP_PKEY_get0_EC_KEY(pkey);
}
#endif
@@ -1377,24 +1394,6 @@ ssl_started(SSL *ssl)
}
static void
-ossl_ssl_shutdown(SSL *ssl)
-{
- int i;
-
- /* 4 is from SSL_smart_shutdown() of mod_ssl.c (v2.2.19) */
- /* It says max 2x pending + 2x data = 4 */
- for (i = 0; i < 4; ++i) {
- /*
- * Ignore the case SSL_shutdown returns -1. Empty handshake_func
- * must not happen.
- */
- if (SSL_shutdown(ssl) != 0)
- break;
- }
- ossl_clear_error();
-}
-
-static void
ossl_ssl_free(void *ssl)
{
SSL_free(ssl);
@@ -1496,19 +1495,15 @@ ossl_ssl_setup(VALUE self)
static void
write_would_block(int nonblock)
{
- if (nonblock) {
- VALUE exc = ossl_exc_new(eSSLErrorWaitWritable, "write would block");
- rb_exc_raise(exc);
- }
+ if (nonblock)
+ ossl_raise(eSSLErrorWaitWritable, "write would block");
}
static void
read_would_block(int nonblock)
{
- if (nonblock) {
- VALUE exc = ossl_exc_new(eSSLErrorWaitReadable, "read would block");
- rb_exc_raise(exc);
- }
+ if (nonblock)
+ ossl_raise(eSSLErrorWaitReadable, "read would block");
}
static int
@@ -1714,11 +1709,21 @@ ossl_ssl_read_internal(int argc, VALUE *argv, VALUE self, int nonblock)
rb_io_wait_readable(FPTR_TO_FD(fptr));
continue;
case SSL_ERROR_SYSCALL:
- if(ERR_peek_error() == 0 && nread == 0) {
- if (no_exception_p(opts)) { return Qnil; }
- rb_eof_error();
+ if (!ERR_peek_error()) {
+ if (errno)
+ rb_sys_fail(0);
+ else {
+ /*
+ * The underlying BIO returned 0. This is actually a
+ * protocol error. But unfortunately, not all
+ * implementations cleanly shutdown the TLS connection
+ * but just shutdown/close the TCP connection. So report
+ * EOF for now...
+ */
+ if (no_exception_p(opts)) { return Qnil; }
+ rb_eof_error();
+ }
}
- rb_sys_fail(0);
default:
ossl_raise(eSSLError, "SSL_read");
}
@@ -1871,11 +1876,24 @@ static VALUE
ossl_ssl_stop(VALUE self)
{
SSL *ssl;
+ int ret;
GetSSL(self, ssl);
+ if (!ssl_started(ssl))
+ return Qnil;
+ ret = SSL_shutdown(ssl);
+ if (ret == 1) /* Have already received close_notify */
+ return Qnil;
+ if (ret == 0) /* Sent close_notify, but we don't wait for reply */
+ return Qnil;
- ossl_ssl_shutdown(ssl);
-
+ /*
+ * XXX: Something happened. Possibly it failed because the underlying socket
+ * is not writable/readable, since it is in non-blocking mode. We should do
+ * some proper error handling using SSL_get_error() and maybe retry, but we
+ * can't block here. Give up for now.
+ */
+ ossl_clear_error();
return Qnil;
}
@@ -2525,6 +2543,7 @@ Init_ossl_ssl(void)
rb_define_method(cSSLContext, "security_level=", ossl_sslctx_set_security_level, 1);
rb_define_method(cSSLContext, "setup", ossl_sslctx_setup, 0);
+ rb_define_alias(cSSLContext, "freeze", "setup");
/*
* No session caching for client or server
@@ -2691,6 +2710,9 @@ Init_ossl_ssl(void)
sym_wait_readable = ID2SYM(rb_intern("wait_readable"));
sym_wait_writable = ID2SYM(rb_intern("wait_writable"));
+ id_tmp_dh_callback = rb_intern("tmp_dh_callback");
+ id_tmp_ecdh_callback = rb_intern("tmp_ecdh_callback");
+
#define DefIVarID(name) do \
id_i_##name = rb_intern("@"#name); while (0)
diff --git a/ext/openssl/ossl_ssl_session.c b/ext/openssl/ossl_ssl_session.c
index fb7c0fb..7abb867 100644
--- a/ext/openssl/ossl_ssl_session.c
+++ b/ext/openssl/ossl_ssl_session.c
@@ -108,11 +108,7 @@ int SSL_SESSION_cmp(const SSL_SESSION *a,const SSL_SESSION *b)
if (a_len != b_len)
return 1;
-#if defined(_WIN32)
- return memcmp(a_sid, b_sid, a_len);
-#else
return CRYPTO_memcmp(a_sid, b_sid, a_len);
-#endif
}
#endif
@@ -141,19 +137,18 @@ static VALUE ossl_ssl_session_eq(VALUE val1, VALUE val2)
*
* Returns the time at which the session was established.
*/
-static VALUE ossl_ssl_session_get_time(VALUE self)
+static VALUE
+ossl_ssl_session_get_time(VALUE self)
{
- SSL_SESSION *ctx;
- time_t t;
-
- GetSSLSession(self, ctx);
-
- t = SSL_SESSION_get_time(ctx);
+ SSL_SESSION *ctx;
+ long t;
- if (t == 0)
- return Qnil;
+ GetSSLSession(self, ctx);
+ t = SSL_SESSION_get_time(ctx);
+ if (t == 0)
+ return Qnil;
- return rb_funcall(rb_cTime, rb_intern("at"), 1, TIMET2NUM(t));
+ return rb_funcall(rb_cTime, rb_intern("at"), 1, LONG2NUM(t));
}
/*
@@ -164,16 +159,16 @@ static VALUE ossl_ssl_session_get_time(VALUE self)
* established time.
*
*/
-static VALUE ossl_ssl_session_get_timeout(VALUE self)
+static VALUE
+ossl_ssl_session_get_timeout(VALUE self)
{
- SSL_SESSION *ctx;
- time_t t;
+ SSL_SESSION *ctx;
+ long t;
- GetSSLSession(self, ctx);
-
- t = SSL_SESSION_get_timeout(ctx);
+ GetSSLSession(self, ctx);
+ t = SSL_SESSION_get_timeout(ctx);
- return TIMET2NUM(t);
+ return LONG2NUM(t);
}
/*
@@ -270,9 +265,6 @@ static VALUE ossl_ssl_session_to_pem(VALUE self)
{
SSL_SESSION *ctx;
BIO *out;
- BUF_MEM *buf;
- VALUE str;
- int i;
GetSSLSession(self, ctx);
@@ -280,16 +272,13 @@ static VALUE ossl_ssl_session_to_pem(VALUE self)
ossl_raise(eSSLSession, "BIO_s_mem()");
}
- if (!(i=PEM_write_bio_SSL_SESSION(out, ctx))) {
+ if (!PEM_write_bio_SSL_SESSION(out, ctx)) {
BIO_free(out);
ossl_raise(eSSLSession, "SSL_SESSION_print()");
}
- BIO_get_mem_ptr(out, &buf);
- str = rb_str_new(buf->data, buf->length);
- BIO_free(out);
- return str;
+ return ossl_membio2str(out);
}
@@ -303,8 +292,6 @@ static VALUE ossl_ssl_session_to_text(VALUE self)
{
SSL_SESSION *ctx;
BIO *out;
- BUF_MEM *buf;
- VALUE str;
GetSSLSession(self, ctx);
@@ -317,11 +304,7 @@ static VALUE ossl_ssl_session_to_text(VALUE self)
ossl_raise(eSSLSession, "SSL_SESSION_print()");
}
- BIO_get_mem_ptr(out, &buf);
- str = rb_str_new(buf->data, buf->length);
- BIO_free(out);
-
- return str;
+ return ossl_membio2str(out);
}
diff --git a/ext/openssl/ossl_x509.h b/ext/openssl/ossl_x509.h
index c26da73..a60f7c3 100644
--- a/ext/openssl/ossl_x509.h
+++ b/ext/openssl/ossl_x509.h
@@ -110,10 +110,13 @@ VALUE ossl_x509store_new(X509_STORE *);
X509_STORE *GetX509StorePtr(VALUE);
X509_STORE *DupX509StorePtr(VALUE);
-VALUE ossl_x509stctx_new(X509_STORE_CTX *);
-VALUE ossl_x509stctx_clear_ptr(VALUE);
X509_STORE_CTX *GetX509StCtxtPtr(VALUE);
-
void Init_ossl_x509store(void);
+/*
+ * Calls the verify callback Proc (the first parameter) with given pre-verify
+ * result and the X509_STORE_CTX.
+ */
+int ossl_verify_cb_call(VALUE, int, X509_STORE_CTX *);
+
#endif /* _OSSL_X509_H_ */
diff --git a/ext/openssl/ossl_x509cert.c b/ext/openssl/ossl_x509cert.c
index ad1126d..cecc3ca 100644
--- a/ext/openssl/ossl_x509cert.c
+++ b/ext/openssl/ossl_x509cert.c
@@ -624,7 +624,7 @@ ossl_x509_check_private_key(VALUE self, VALUE key)
pkey = GetPrivPKeyPtr(key); /* NO NEED TO DUP */
GetX509(self, x509);
if (!X509_check_private_key(x509, pkey)) {
- OSSL_Warning("Check private key:%s", OSSL_ErrMsg());
+ ossl_clear_error();
return Qfalse;
}
diff --git a/ext/openssl/ossl_x509crl.c b/ext/openssl/ossl_x509crl.c
index 0ff5d2f..f9819f5 100644
--- a/ext/openssl/ossl_x509crl.c
+++ b/ext/openssl/ossl_x509crl.c
@@ -182,8 +182,6 @@ ossl_x509crl_get_signature_algorithm(VALUE self)
X509_CRL *crl;
const X509_ALGOR *alg;
BIO *out;
- BUF_MEM *buf;
- VALUE str;
GetX509CRL(self, crl);
if (!(out = BIO_new(BIO_s_mem()))) {
@@ -194,10 +192,8 @@ ossl_x509crl_get_signature_algorithm(VALUE self)
BIO_free(out);
ossl_raise(eX509CRLError, NULL);
}
- BIO_get_mem_ptr(out, &buf);
- str = rb_str_new(buf->data, buf->length);
- BIO_free(out);
- return str;
+
+ return ossl_membio2str(out);
}
static VALUE
@@ -388,8 +384,6 @@ ossl_x509crl_to_der(VALUE self)
{
X509_CRL *crl;
BIO *out;
- BUF_MEM *buf;
- VALUE str;
GetX509CRL(self, crl);
if (!(out = BIO_new(BIO_s_mem()))) {
@@ -399,11 +393,8 @@ ossl_x509crl_to_der(VALUE self)
BIO_free(out);
ossl_raise(eX509CRLError, NULL);
}
- BIO_get_mem_ptr(out, &buf);
- str = rb_str_new(buf->data, buf->length);
- BIO_free(out);
- return str;
+ return ossl_membio2str(out);
}
static VALUE
@@ -411,8 +402,6 @@ ossl_x509crl_to_pem(VALUE self)
{
X509_CRL *crl;
BIO *out;
- BUF_MEM *buf;
- VALUE str;
GetX509CRL(self, crl);
if (!(out = BIO_new(BIO_s_mem()))) {
@@ -422,11 +411,8 @@ ossl_x509crl_to_pem(VALUE self)
BIO_free(out);
ossl_raise(eX509CRLError, NULL);
}
- BIO_get_mem_ptr(out, &buf);
- str = rb_str_new(buf->data, buf->length);
- BIO_free(out);
- return str;
+ return ossl_membio2str(out);
}
static VALUE
@@ -434,8 +420,6 @@ ossl_x509crl_to_text(VALUE self)
{
X509_CRL *crl;
BIO *out;
- BUF_MEM *buf;
- VALUE str;
GetX509CRL(self, crl);
if (!(out = BIO_new(BIO_s_mem()))) {
@@ -445,11 +429,8 @@ ossl_x509crl_to_text(VALUE self)
BIO_free(out);
ossl_raise(eX509CRLError, NULL);
}
- BIO_get_mem_ptr(out, &buf);
- str = rb_str_new(buf->data, buf->length);
- BIO_free(out);
- return str;
+ return ossl_membio2str(out);
}
/*
diff --git a/ext/openssl/ossl_x509name.c b/ext/openssl/ossl_x509name.c
index abbdc3b..4523e0d 100644
--- a/ext/openssl/ossl_x509name.c
+++ b/ext/openssl/ossl_x509name.c
@@ -372,12 +372,10 @@ ossl_x509name_cmp(VALUE self, VALUE other)
static VALUE
ossl_x509name_eql(VALUE self, VALUE other)
{
- int result;
-
- if(CLASS_OF(other) != cX509Name) return Qfalse;
- result = ossl_x509name_cmp0(self, other);
+ if (!rb_obj_is_kind_of(other, cX509Name))
+ return Qfalse;
- return (result == 0) ? Qtrue : Qfalse;
+ return ossl_x509name_cmp0(self, other) ? Qtrue : Qfalse;
}
/*
diff --git a/ext/openssl/ossl_x509req.c b/ext/openssl/ossl_x509req.c
index d261997..220d2f4 100644
--- a/ext/openssl/ossl_x509req.c
+++ b/ext/openssl/ossl_x509req.c
@@ -160,8 +160,6 @@ ossl_x509req_to_pem(VALUE self)
{
X509_REQ *req;
BIO *out;
- BUF_MEM *buf;
- VALUE str;
GetX509Req(self, req);
if (!(out = BIO_new(BIO_s_mem()))) {
@@ -171,11 +169,8 @@ ossl_x509req_to_pem(VALUE self)
BIO_free(out);
ossl_raise(eX509ReqError, NULL);
}
- BIO_get_mem_ptr(out, &buf);
- str = rb_str_new(buf->data, buf->length);
- BIO_free(out);
- return str;
+ return ossl_membio2str(out);
}
static VALUE
@@ -203,8 +198,6 @@ ossl_x509req_to_text(VALUE self)
{
X509_REQ *req;
BIO *out;
- BUF_MEM *buf;
- VALUE str;
GetX509Req(self, req);
if (!(out = BIO_new(BIO_s_mem()))) {
@@ -214,11 +207,8 @@ ossl_x509req_to_text(VALUE self)
BIO_free(out);
ossl_raise(eX509ReqError, NULL);
}
- BIO_get_mem_ptr(out, &buf);
- str = rb_str_new(buf->data, buf->length);
- BIO_free(out);
- return str;
+ return ossl_membio2str(out);
}
#if 0
@@ -304,8 +294,6 @@ ossl_x509req_get_signature_algorithm(VALUE self)
X509_REQ *req;
const X509_ALGOR *alg;
BIO *out;
- BUF_MEM *buf;
- VALUE str;
GetX509Req(self, req);
@@ -317,10 +305,8 @@ ossl_x509req_get_signature_algorithm(VALUE self)
BIO_free(out);
ossl_raise(eX509ReqError, NULL);
}
- BIO_get_mem_ptr(out, &buf);
- str = rb_str_new(buf->data, buf->length);
- BIO_free(out);
- return str;
+
+ return ossl_membio2str(out);
}
static VALUE
diff --git a/ext/openssl/ossl_x509store.c b/ext/openssl/ossl_x509store.c
index 75f8238..eb81e0d 100644
--- a/ext/openssl/ossl_x509store.c
+++ b/ext/openssl/ossl_x509store.c
@@ -48,6 +48,65 @@
} while (0)
/*
+ * Verify callback stuff
+ */
+static int stctx_ex_verify_cb_idx, store_ex_verify_cb_idx;
+static VALUE ossl_x509stctx_new(X509_STORE_CTX *);
+
+struct ossl_verify_cb_args {
+ VALUE proc;
+ VALUE preverify_ok;
+ VALUE store_ctx;
+};
+
+static VALUE
+call_verify_cb_proc(struct ossl_verify_cb_args *args)
+{
+ return rb_funcall(args->proc, rb_intern("call"), 2,
+ args->preverify_ok, args->store_ctx);
+}
+
+int
+ossl_verify_cb_call(VALUE proc, int ok, X509_STORE_CTX *ctx)
+{
+ VALUE rctx, ret;
+ struct ossl_verify_cb_args args;
+ int state;
+
+ if (NIL_P(proc))
+ return ok;
+
+ ret = Qfalse;
+ rctx = rb_protect((VALUE(*)(VALUE))ossl_x509stctx_new, (VALUE)ctx, &state);
+ if (state) {
+ rb_set_errinfo(Qnil);
+ rb_warn("StoreContext initialization failure");
+ }
+ else {
+ args.proc = proc;
+ args.preverify_ok = ok ? Qtrue : Qfalse;
+ args.store_ctx = rctx;
+ ret = rb_protect((VALUE(*)(VALUE))call_verify_cb_proc, (VALUE)&args, &state);
+ if (state) {
+ rb_set_errinfo(Qnil);
+ rb_warn("exception in verify_callback is ignored");
+ }
+ RTYPEDDATA_DATA(rctx) = NULL;
+ }
+ if (ret == Qtrue) {
+ X509_STORE_CTX_set_error(ctx, X509_V_OK);
+ ok = 1;
+ }
+ else {
+ if (X509_STORE_CTX_get_error(ctx) == X509_V_OK)
+ X509_STORE_CTX_set_error(ctx, X509_V_ERR_CERT_REJECTED);
+ ok = 0;
+ }
+
+ return ok;
+}
+
+/*
* Classes
*/
VALUE cX509Store;
@@ -111,9 +170,10 @@ x509store_verify_cb(int ok, X509_STORE_CTX *ctx)
{
VALUE proc;
- proc = (VALUE)X509_STORE_CTX_get_ex_data(ctx, ossl_store_ctx_ex_verify_cb_idx);
+ proc = (VALUE)X509_STORE_CTX_get_ex_data(ctx, stctx_ex_verify_cb_idx);
if (!proc)
- proc = (VALUE)X509_STORE_get_ex_data(X509_STORE_CTX_get0_store(ctx), ossl_store_ex_verify_cb_idx);
+ proc = (VALUE)X509_STORE_get_ex_data(X509_STORE_CTX_get0_store(ctx),
+ store_ex_verify_cb_idx);
if (!proc)
return ok;
@@ -144,7 +204,7 @@ ossl_x509store_set_vfy_cb(VALUE self, VALUE cb)
X509_STORE *store;
GetX509Store(self, store);
- X509_STORE_set_ex_data(store, ossl_store_ex_verify_cb_idx, (void *)cb);
+ X509_STORE_set_ex_data(store, store_ex_verify_cb_idx, (void *)cb);
rb_iv_set(self, "@verify_callback", cb);
return cb;
@@ -432,27 +492,6 @@ static const rb_data_type_t ossl_x509stctx_type = {
0, 0, RUBY_TYPED_FREE_IMMEDIATELY,
};
-
-VALUE
-ossl_x509stctx_new(X509_STORE_CTX *ctx)
-{
- VALUE obj;
-
- obj = NewX509StCtx(cX509StoreContext);
- SetX509StCtx(obj, ctx);
-
- return obj;
-}
-
-VALUE
-ossl_x509stctx_clear_ptr(VALUE obj)
-{
- OSSL_Check_Kind(obj, cX509StoreContext);
- RDATA(obj)->data = NULL;
-
- return obj;
-}
-
/*
* Private functions
*/
@@ -482,6 +521,17 @@ ossl_x509stctx_alloc(VALUE klass)
return obj;
}
+static VALUE
+ossl_x509stctx_new(X509_STORE_CTX *ctx)
+{
+ VALUE obj;
+
+ obj = NewX509StCtx(cX509StoreContext);
+ SetX509StCtx(obj, ctx);
+
+ return obj;
+}
+
static VALUE ossl_x509stctx_set_flags(VALUE, VALUE);
static VALUE ossl_x509stctx_set_purpose(VALUE, VALUE);
static VALUE ossl_x509stctx_set_trust(VALUE, VALUE);
@@ -527,7 +577,7 @@ ossl_x509stctx_verify(VALUE self)
X509_STORE_CTX *ctx;
GetX509StCtx(self, ctx);
- X509_STORE_CTX_set_ex_data(ctx, ossl_store_ctx_ex_verify_cb_idx,
+ X509_STORE_CTX_set_ex_data(ctx, stctx_ex_verify_cb_idx,
(void *)rb_iv_get(self, "@verify_callback"));
switch (X509_verify_cert(ctx)) {
@@ -747,6 +797,14 @@ Init_ossl_x509store(void)
mX509 = rb_define_module_under(mOSSL, "X509");
#endif
+ /* Register ext_data slot for verify callback Proc */
+ stctx_ex_verify_cb_idx = X509_STORE_CTX_get_ex_new_index(0, (void *)"stctx_ex_verify_cb_idx", 0, 0, 0);
+ if (stctx_ex_verify_cb_idx < 0)
+ ossl_raise(eOSSLError, "X509_STORE_CTX_get_ex_new_index");
+ store_ex_verify_cb_idx = X509_STORE_get_ex_new_index(0, (void *)"store_ex_verify_cb_idx", 0, 0, 0);
+ if (store_ex_verify_cb_idx < 0)
+ ossl_raise(eOSSLError, "X509_STORE_get_ex_new_index");
+
eX509StoreError = rb_define_class_under(mX509, "StoreError", eOSSLError);
/* Document-class: OpenSSL::X509::Store
diff --git a/ext/openssl/ruby_missing.h b/ext/openssl/ruby_missing.h
index f076b17..8dacc82 100644
--- a/ext/openssl/ruby_missing.h
+++ b/ext/openssl/ruby_missing.h
@@ -13,16 +13,7 @@
#define rb_define_copy_func(klass, func) \
rb_define_method((klass), "initialize_copy", (func), 1)
-
-#ifndef GetReadFile
#define FPTR_TO_FD(fptr) ((fptr)->fd)
-#else
-#define FPTR_TO_FD(fptr) (fileno(GetReadFile(fptr)))
-#endif
-
-#ifndef HAVE_RB_IO_T
-#define rb_io_t OpenFile
-#endif
#ifndef RB_INTEGER_TYPE_P
/* for Ruby 2.3 compatibility */