зеркало из https://github.com/github/ruby.git
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
This commit is contained in:
Родитель
0a5abaf745
Коммит
aab0d67a1f
7
NEWS
7
NEWS
|
@ -217,9 +217,10 @@ with all sufficient information, see the ChangeLog file or Redmine
|
|||
|
||||
* OpenSSL
|
||||
|
||||
* OpenSSL is extracted as a gem and the upstream has been migrated to
|
||||
https://github.com/ruby/openssl. OpenSSL still remains as a default gem.
|
||||
Refer to its History.md for the full release note. [Feature #9612]
|
||||
* Includes Ruby/OpenSSL 2.0. OpenSSL has been extracted as a Gem and is
|
||||
maintained at a separate repository now: https://github.com/ruby/openssl.
|
||||
It still remains as a 'default gem'. [Feature #9612]
|
||||
Refer to ext/openssl/History.md for the full release note.
|
||||
|
||||
* optparse
|
||||
|
||||
|
|
|
@ -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.
|
|
@ -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")
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -1151,14 +1098,6 @@ Init_openssl(void)
|
|||
rb_define_module_function(mOSSL, "debug=", ossl_debug_set, 1);
|
||||
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
|
||||
*/
|
||||
|
|
|
@ -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,18 +117,9 @@ 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
|
||||
*/
|
||||
|
|
|
@ -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");
|
||||
}
|
||||
|
|
|
@ -8,9 +8,6 @@
|
|||
* (See the file 'LICENCE'.)
|
||||
*/
|
||||
#include "ossl.h"
|
||||
#ifdef HAVE_UNISTD_H
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
BIO *
|
||||
ossl_obj2bio(VALUE obj)
|
||||
|
|
|
@ -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); \
|
||||
} \
|
||||
|
|
|
@ -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:
|
||||
|
@ -675,23 +693,6 @@ ossl_cipher_set_auth_tag_len(VALUE self, VALUE vlen)
|
|||
return 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");
|
||||
}
|
||||
|
|
|
@ -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)) {
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
VALUE obj;
|
||||
int status;
|
||||
|
||||
rb_check_safe_obj(filename);
|
||||
if (!(fp = fopen(StringValueCStr(filename), "r"))) {
|
||||
ossl_raise(ePKeyError, "%s", strerror(errno));
|
||||
}
|
||||
rb_fd_fix_cloexec(fileno(fp));
|
||||
|
||||
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 */
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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) */
|
||||
|
|
|
@ -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
|
||||
*
|
||||
* See the OpenSSL documentation for EC_POINT_point2bn()
|
||||
* 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 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");
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
||||
args = rb_ary_new_from_args(3, rb_ssl, INT2NUM(is_export), INT2NUM(keylength));
|
||||
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;
|
||||
|
||||
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;
|
||||
|
||||
args = rb_ary_new_from_args(3, rb_ssl, INT2NUM(is_export), INT2NUM(keylength));
|
||||
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;
|
||||
|
||||
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
|
||||
|
||||
|
@ -1376,24 +1393,6 @@ ssl_started(SSL *ssl)
|
|||
return SSL_get_fd(ssl) >= 0;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
|
@ -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)
|
||||
|
||||
|
|
|
@ -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;
|
||||
SSL_SESSION *ctx;
|
||||
long t;
|
||||
|
||||
GetSSLSession(self, ctx);
|
||||
GetSSLSession(self, ctx);
|
||||
t = SSL_SESSION_get_time(ctx);
|
||||
if (t == 0)
|
||||
return Qnil;
|
||||
|
||||
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);
|
||||
GetSSLSession(self, ctx);
|
||||
t = SSL_SESSION_get_timeout(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);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -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_ */
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -372,12 +372,10 @@ ossl_x509name_cmp(VALUE self, VALUE other)
|
|||
static VALUE
|
||||
ossl_x509name_eql(VALUE self, VALUE other)
|
||||
{
|
||||
int result;
|
||||
if (!rb_obj_is_kind_of(other, cX509Name))
|
||||
return Qfalse;
|
||||
|
||||
if(CLASS_OF(other) != cX509Name) return Qfalse;
|
||||
result = ossl_x509name_cmp0(self, other);
|
||||
|
||||
return (result == 0) ? Qtrue : Qfalse;
|
||||
return ossl_x509name_cmp0(self, other) ? Qtrue : Qfalse;
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -47,6 +47,65 @@
|
|||
GetX509Store((obj), (ctx)); \
|
||||
} 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
|
||||
*/
|
||||
|
@ -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
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -14,7 +14,7 @@ class OpenSSL::TestASN1 < OpenSSL::TestCase
|
|||
]
|
||||
dgst = OpenSSL::Digest::SHA1.new
|
||||
cert = OpenSSL::TestUtils.issue_cert(
|
||||
subj, key, s, now, now+3600, exts, nil, nil, dgst)
|
||||
subj, key, s, exts, nil, nil, digest: dgst, not_before: now, not_after: now+3600)
|
||||
|
||||
|
||||
asn1 = OpenSSL::ASN1.decode(cert)
|
||||
|
@ -243,14 +243,9 @@ rEzBQ0F9dUyqQ9gyRg8KHhDfv9HzT1d/rnUZMkoombwYBRIUChGCYV0GnJcan2Zm
|
|||
end
|
||||
|
||||
def test_primitive_cannot_set_infinite_length
|
||||
begin
|
||||
prim = OpenSSL::ASN1::Integer.new(50)
|
||||
assert_equal(false, prim.infinite_length)
|
||||
prim.infinite_length = true
|
||||
flunk('Could set infinite length on primitive value')
|
||||
rescue NoMethodError
|
||||
#ok
|
||||
end
|
||||
prim = OpenSSL::ASN1::Integer.new(50)
|
||||
assert_equal false, prim.infinite_length
|
||||
assert_not_respond_to prim, :infinite_length=
|
||||
end
|
||||
|
||||
def test_decode_all
|
||||
|
@ -289,12 +284,8 @@ rEzBQ0F9dUyqQ9gyRg8KHhDfv9HzT1d/rnUZMkoombwYBRIUChGCYV0GnJcan2Zm
|
|||
def test_create_inf_length_primitive
|
||||
expected = %w{ 24 80 04 01 61 00 00 }
|
||||
raw = [expected.join('')].pack('H*')
|
||||
val = OpenSSL::ASN1::OctetString.new('a')
|
||||
cons = OpenSSL::ASN1::Constructive.new([val,
|
||||
OpenSSL::ASN1::EndOfContent.new],
|
||||
OpenSSL::ASN1::OCTET_STRING,
|
||||
nil,
|
||||
:UNIVERSAL)
|
||||
content = [OpenSSL::ASN1::OctetString.new("a"), OpenSSL::ASN1::EndOfContent.new]
|
||||
cons = OpenSSL::ASN1::Constructive.new(content, OpenSSL::ASN1::OCTET_STRING, nil, :UNIVERSAL)
|
||||
cons.infinite_length = true
|
||||
assert_equal(nil, cons.tagging)
|
||||
assert_equal(raw, cons.to_der)
|
||||
|
@ -306,10 +297,7 @@ rEzBQ0F9dUyqQ9gyRg8KHhDfv9HzT1d/rnUZMkoombwYBRIUChGCYV0GnJcan2Zm
|
|||
def test_cons_without_inf_length_forbidden
|
||||
assert_raise(OpenSSL::ASN1::ASN1Error) do
|
||||
val = OpenSSL::ASN1::OctetString.new('a')
|
||||
cons = OpenSSL::ASN1::Constructive.new([val],
|
||||
OpenSSL::ASN1::OCTET_STRING,
|
||||
nil,
|
||||
:UNIVERSAL)
|
||||
cons = OpenSSL::ASN1::Constructive.new([val], OpenSSL::ASN1::OCTET_STRING, nil, :UNIVERSAL)
|
||||
cons.to_der
|
||||
end
|
||||
end
|
||||
|
@ -317,10 +305,7 @@ rEzBQ0F9dUyqQ9gyRg8KHhDfv9HzT1d/rnUZMkoombwYBRIUChGCYV0GnJcan2Zm
|
|||
def test_cons_without_array_forbidden
|
||||
assert_raise(OpenSSL::ASN1::ASN1Error) do
|
||||
val = OpenSSL::ASN1::OctetString.new('a')
|
||||
cons = OpenSSL::ASN1::Constructive.new(val,
|
||||
OpenSSL::ASN1::OCTET_STRING,
|
||||
nil,
|
||||
:UNIVERSAL)
|
||||
cons = OpenSSL::ASN1::Constructive.new(val, OpenSSL::ASN1::OCTET_STRING, nil, :UNIVERSAL)
|
||||
cons.infinite_length = true
|
||||
cons.to_der
|
||||
end
|
||||
|
@ -352,218 +337,158 @@ rEzBQ0F9dUyqQ9gyRg8KHhDfv9HzT1d/rnUZMkoombwYBRIUChGCYV0GnJcan2Zm
|
|||
end
|
||||
|
||||
def test_seq_infinite_length
|
||||
begin
|
||||
content = [ OpenSSL::ASN1::Null.new(nil),
|
||||
OpenSSL::ASN1::EndOfContent.new ]
|
||||
cons = OpenSSL::ASN1::Sequence.new(content)
|
||||
cons.infinite_length = true
|
||||
expected = %w{ 30 80 05 00 00 00 }
|
||||
raw = [expected.join('')].pack('H*')
|
||||
assert_equal(raw, cons.to_der)
|
||||
assert_equal(raw, OpenSSL::ASN1.decode(raw).to_der)
|
||||
end
|
||||
content = [ OpenSSL::ASN1::Null.new(nil),
|
||||
OpenSSL::ASN1::EndOfContent.new ]
|
||||
cons = OpenSSL::ASN1::Sequence.new(content)
|
||||
cons.infinite_length = true
|
||||
expected = %w{ 30 80 05 00 00 00 }
|
||||
raw = [expected.join('')].pack('H*')
|
||||
assert_equal(raw, cons.to_der)
|
||||
assert_equal(raw, OpenSSL::ASN1.decode(raw).to_der)
|
||||
end
|
||||
|
||||
def test_set_infinite_length
|
||||
begin
|
||||
content = [ OpenSSL::ASN1::Null.new(nil),
|
||||
OpenSSL::ASN1::EndOfContent.new() ]
|
||||
cons = OpenSSL::ASN1::Set.new(content)
|
||||
cons.infinite_length = true
|
||||
expected = %w{ 31 80 05 00 00 00 }
|
||||
raw = [expected.join('')].pack('H*')
|
||||
assert_equal(raw, cons.to_der)
|
||||
assert_equal(raw, OpenSSL::ASN1.decode(raw).to_der)
|
||||
end
|
||||
content = [ OpenSSL::ASN1::Null.new(nil),
|
||||
OpenSSL::ASN1::EndOfContent.new() ]
|
||||
cons = OpenSSL::ASN1::Set.new(content)
|
||||
cons.infinite_length = true
|
||||
expected = %w{ 31 80 05 00 00 00 }
|
||||
raw = [expected.join('')].pack('H*')
|
||||
assert_equal(raw, cons.to_der)
|
||||
assert_equal(raw, OpenSSL::ASN1.decode(raw).to_der)
|
||||
end
|
||||
|
||||
def test_octet_string_infinite_length
|
||||
begin
|
||||
octets = [ OpenSSL::ASN1::OctetString.new('aaa'),
|
||||
OpenSSL::ASN1::EndOfContent.new() ]
|
||||
cons = OpenSSL::ASN1::Constructive.new(
|
||||
octets,
|
||||
OpenSSL::ASN1::OCTET_STRING,
|
||||
nil,
|
||||
:UNIVERSAL)
|
||||
cons.infinite_length = true
|
||||
expected = %w{ 24 80 04 03 61 61 61 00 00 }
|
||||
raw = [expected.join('')].pack('H*')
|
||||
assert_equal(raw, cons.to_der)
|
||||
assert_equal(raw, OpenSSL::ASN1.decode(raw).to_der)
|
||||
end
|
||||
octets = [ OpenSSL::ASN1::OctetString.new('aaa'),
|
||||
OpenSSL::ASN1::EndOfContent.new() ]
|
||||
cons = OpenSSL::ASN1::Constructive.new(octets, OpenSSL::ASN1::OCTET_STRING, nil, :UNIVERSAL)
|
||||
cons.infinite_length = true
|
||||
expected = %w{ 24 80 04 03 61 61 61 00 00 }
|
||||
raw = [expected.join('')].pack('H*')
|
||||
assert_equal(raw, cons.to_der)
|
||||
assert_equal(raw, OpenSSL::ASN1.decode(raw).to_der)
|
||||
end
|
||||
|
||||
def test_prim_explicit_tagging
|
||||
begin
|
||||
oct_str = OpenSSL::ASN1::OctetString.new("a", 0, :EXPLICIT)
|
||||
expected = %w{ A0 03 04 01 61 }
|
||||
raw = [expected.join('')].pack('H*')
|
||||
assert_equal(raw, oct_str.to_der)
|
||||
assert_equal(raw, OpenSSL::ASN1.decode(raw).to_der)
|
||||
end
|
||||
oct_str = OpenSSL::ASN1::OctetString.new("a", 0, :EXPLICIT)
|
||||
expected = %w{ A0 03 04 01 61 }
|
||||
raw = [expected.join('')].pack('H*')
|
||||
assert_equal(raw, oct_str.to_der)
|
||||
assert_equal(raw, OpenSSL::ASN1.decode(raw).to_der)
|
||||
end
|
||||
|
||||
def test_prim_explicit_tagging_tag_class
|
||||
begin
|
||||
oct_str = OpenSSL::ASN1::OctetString.new("a", 0, :EXPLICIT)
|
||||
oct_str2 = OpenSSL::ASN1::OctetString.new(
|
||||
"a",
|
||||
0,
|
||||
:EXPLICIT,
|
||||
:CONTEXT_SPECIFIC)
|
||||
assert_equal(oct_str.to_der, oct_str2.to_der)
|
||||
end
|
||||
oct_str = OpenSSL::ASN1::OctetString.new("a", 0, :EXPLICIT)
|
||||
oct_str2 = OpenSSL::ASN1::OctetString.new("a", 0, :EXPLICIT, :CONTEXT_SPECIFIC)
|
||||
assert_equal(oct_str.to_der, oct_str2.to_der)
|
||||
end
|
||||
|
||||
def test_prim_implicit_tagging
|
||||
begin
|
||||
int = OpenSSL::ASN1::Integer.new(1, 0, :IMPLICIT)
|
||||
expected = %w{ 80 01 01 }
|
||||
raw = [expected.join('')].pack('H*')
|
||||
assert_equal(raw, int.to_der)
|
||||
assert_equal(raw, OpenSSL::ASN1.decode(raw).to_der)
|
||||
end
|
||||
int = OpenSSL::ASN1::Integer.new(1, 0, :IMPLICIT)
|
||||
expected = %w{ 80 01 01 }
|
||||
raw = [expected.join('')].pack('H*')
|
||||
assert_equal(raw, int.to_der)
|
||||
assert_equal(raw, OpenSSL::ASN1.decode(raw).to_der)
|
||||
end
|
||||
|
||||
def test_prim_implicit_tagging_tag_class
|
||||
begin
|
||||
int = OpenSSL::ASN1::Integer.new(1, 0, :IMPLICIT)
|
||||
int2 = OpenSSL::ASN1::Integer.new(1, 0, :IMPLICIT, :CONTEXT_SPECIFIC);
|
||||
assert_equal(int.to_der, int2.to_der)
|
||||
end
|
||||
int = OpenSSL::ASN1::Integer.new(1, 0, :IMPLICIT)
|
||||
int2 = OpenSSL::ASN1::Integer.new(1, 0, :IMPLICIT, :CONTEXT_SPECIFIC);
|
||||
assert_equal(int.to_der, int2.to_der)
|
||||
end
|
||||
|
||||
def test_cons_explicit_tagging
|
||||
begin
|
||||
content = [ OpenSSL::ASN1::PrintableString.new('abc') ]
|
||||
seq = OpenSSL::ASN1::Sequence.new(content, 2, :EXPLICIT)
|
||||
expected = %w{ A2 07 30 05 13 03 61 62 63 }
|
||||
raw = [expected.join('')].pack('H*')
|
||||
assert_equal(raw, seq.to_der)
|
||||
assert_equal(raw, OpenSSL::ASN1.decode(raw).to_der)
|
||||
end
|
||||
content = [ OpenSSL::ASN1::PrintableString.new('abc') ]
|
||||
seq = OpenSSL::ASN1::Sequence.new(content, 2, :EXPLICIT)
|
||||
expected = %w{ A2 07 30 05 13 03 61 62 63 }
|
||||
raw = [expected.join('')].pack('H*')
|
||||
assert_equal(raw, seq.to_der)
|
||||
assert_equal(raw, OpenSSL::ASN1.decode(raw).to_der)
|
||||
end
|
||||
|
||||
def test_cons_explicit_tagging_inf_length
|
||||
begin
|
||||
content = [ OpenSSL::ASN1::PrintableString.new('abc') ,
|
||||
OpenSSL::ASN1::EndOfContent.new() ]
|
||||
seq = OpenSSL::ASN1::Sequence.new(content, 2, :EXPLICIT)
|
||||
seq.infinite_length = true
|
||||
expected = %w{ A2 80 30 80 13 03 61 62 63 00 00 00 00 }
|
||||
raw = [expected.join('')].pack('H*')
|
||||
assert_equal(raw, seq.to_der)
|
||||
assert_equal(raw, OpenSSL::ASN1.decode(raw).to_der)
|
||||
end
|
||||
content = [ OpenSSL::ASN1::PrintableString.new('abc') ,
|
||||
OpenSSL::ASN1::EndOfContent.new() ]
|
||||
seq = OpenSSL::ASN1::Sequence.new(content, 2, :EXPLICIT)
|
||||
seq.infinite_length = true
|
||||
expected = %w{ A2 80 30 80 13 03 61 62 63 00 00 00 00 }
|
||||
raw = [expected.join('')].pack('H*')
|
||||
assert_equal(raw, seq.to_der)
|
||||
assert_equal(raw, OpenSSL::ASN1.decode(raw).to_der)
|
||||
end
|
||||
|
||||
def test_cons_implicit_tagging
|
||||
begin
|
||||
content = [ OpenSSL::ASN1::Null.new(nil) ]
|
||||
seq = OpenSSL::ASN1::Sequence.new(content, 1, :IMPLICIT)
|
||||
expected = %w{ A1 02 05 00 }
|
||||
raw = [expected.join('')].pack('H*')
|
||||
assert_equal(raw, seq.to_der)
|
||||
assert_equal(raw, OpenSSL::ASN1.decode(raw).to_der)
|
||||
end
|
||||
content = [ OpenSSL::ASN1::Null.new(nil) ]
|
||||
seq = OpenSSL::ASN1::Sequence.new(content, 1, :IMPLICIT)
|
||||
expected = %w{ A1 02 05 00 }
|
||||
raw = [expected.join('')].pack('H*')
|
||||
assert_equal(raw, seq.to_der)
|
||||
assert_equal(raw, OpenSSL::ASN1.decode(raw).to_der)
|
||||
end
|
||||
|
||||
def test_cons_implicit_tagging_inf_length
|
||||
begin
|
||||
content = [ OpenSSL::ASN1::Null.new(nil),
|
||||
OpenSSL::ASN1::EndOfContent.new() ]
|
||||
seq = OpenSSL::ASN1::Sequence.new(content, 1, :IMPLICIT)
|
||||
seq.infinite_length = true
|
||||
expected = %w{ A1 80 05 00 00 00 }
|
||||
raw = [expected.join('')].pack('H*')
|
||||
assert_equal(raw, seq.to_der)
|
||||
assert_equal(raw, OpenSSL::ASN1.decode(raw).to_der)
|
||||
end
|
||||
content = [ OpenSSL::ASN1::Null.new(nil),
|
||||
OpenSSL::ASN1::EndOfContent.new() ]
|
||||
seq = OpenSSL::ASN1::Sequence.new(content, 1, :IMPLICIT)
|
||||
seq.infinite_length = true
|
||||
expected = %w{ A1 80 05 00 00 00 }
|
||||
raw = [expected.join('')].pack('H*')
|
||||
assert_equal(raw, seq.to_der)
|
||||
assert_equal(raw, OpenSSL::ASN1.decode(raw).to_der)
|
||||
end
|
||||
|
||||
def test_octet_string_infinite_length_explicit_tagging
|
||||
begin
|
||||
octets = [ OpenSSL::ASN1::OctetString.new('aaa'),
|
||||
OpenSSL::ASN1::EndOfContent.new() ]
|
||||
cons = OpenSSL::ASN1::Constructive.new(
|
||||
octets,
|
||||
1,
|
||||
:EXPLICIT)
|
||||
cons.infinite_length = true
|
||||
expected = %w{ A1 80 24 80 04 03 61 61 61 00 00 00 00 }
|
||||
raw = [expected.join('')].pack('H*')
|
||||
assert_equal(raw, cons.to_der)
|
||||
assert_equal(raw, OpenSSL::ASN1.decode(raw).to_der)
|
||||
end
|
||||
octets = [ OpenSSL::ASN1::OctetString.new('aaa'),
|
||||
OpenSSL::ASN1::EndOfContent.new() ]
|
||||
cons = OpenSSL::ASN1::Constructive.new(octets, 1, :EXPLICIT)
|
||||
cons.infinite_length = true
|
||||
expected = %w{ A1 80 24 80 04 03 61 61 61 00 00 00 00 }
|
||||
raw = [expected.join('')].pack('H*')
|
||||
assert_equal(raw, cons.to_der)
|
||||
assert_equal(raw, OpenSSL::ASN1.decode(raw).to_der)
|
||||
end
|
||||
|
||||
def test_octet_string_infinite_length_implicit_tagging
|
||||
begin
|
||||
octets = [ OpenSSL::ASN1::OctetString.new('aaa'),
|
||||
OpenSSL::ASN1::EndOfContent.new() ]
|
||||
cons = OpenSSL::ASN1::Constructive.new(
|
||||
octets,
|
||||
0,
|
||||
:IMPLICIT)
|
||||
cons.infinite_length = true
|
||||
expected = %w{ A0 80 04 03 61 61 61 00 00 }
|
||||
raw = [expected.join('')].pack('H*')
|
||||
assert_equal(raw, cons.to_der)
|
||||
assert_equal(raw, OpenSSL::ASN1.decode(raw).to_der)
|
||||
end
|
||||
octets = [ OpenSSL::ASN1::OctetString.new('aaa'),
|
||||
OpenSSL::ASN1::EndOfContent.new() ]
|
||||
cons = OpenSSL::ASN1::Constructive.new(octets, 0, :IMPLICIT)
|
||||
cons.infinite_length = true
|
||||
expected = %w{ A0 80 04 03 61 61 61 00 00 }
|
||||
raw = [expected.join('')].pack('H*')
|
||||
assert_equal(raw, cons.to_der)
|
||||
assert_equal(raw, OpenSSL::ASN1.decode(raw).to_der)
|
||||
end
|
||||
|
||||
def test_recursive_octet_string_infinite_length
|
||||
begin
|
||||
octets_sub1 = [ OpenSSL::ASN1::OctetString.new("\x01"),
|
||||
OpenSSL::ASN1::EndOfContent.new() ]
|
||||
octets_sub2 = [ OpenSSL::ASN1::OctetString.new("\x02"),
|
||||
OpenSSL::ASN1::EndOfContent.new() ]
|
||||
container1 = OpenSSL::ASN1::Constructive.new(
|
||||
octets_sub1,
|
||||
OpenSSL::ASN1::OCTET_STRING,
|
||||
nil,
|
||||
:UNIVERSAL)
|
||||
container1.infinite_length = true
|
||||
container2 = OpenSSL::ASN1::Constructive.new(
|
||||
octets_sub2,
|
||||
OpenSSL::ASN1::OCTET_STRING,
|
||||
nil,
|
||||
:UNIVERSAL)
|
||||
container2.infinite_length = true
|
||||
octets3 = OpenSSL::ASN1::OctetString.new("\x03")
|
||||
octets_sub1 = [ OpenSSL::ASN1::OctetString.new("\x01"),
|
||||
OpenSSL::ASN1::EndOfContent.new() ]
|
||||
octets_sub2 = [ OpenSSL::ASN1::OctetString.new("\x02"),
|
||||
OpenSSL::ASN1::EndOfContent.new() ]
|
||||
container1 = OpenSSL::ASN1::Constructive.new(octets_sub1, OpenSSL::ASN1::OCTET_STRING, nil, :UNIVERSAL)
|
||||
container1.infinite_length = true
|
||||
container2 = OpenSSL::ASN1::Constructive.new(octets_sub2, OpenSSL::ASN1::OCTET_STRING, nil, :UNIVERSAL)
|
||||
container2.infinite_length = true
|
||||
octets3 = OpenSSL::ASN1::OctetString.new("\x03")
|
||||
|
||||
octets = [ container1, container2, octets3,
|
||||
OpenSSL::ASN1::EndOfContent.new() ]
|
||||
cons = OpenSSL::ASN1::Constructive.new(
|
||||
octets,
|
||||
OpenSSL::ASN1::OCTET_STRING,
|
||||
nil,
|
||||
:UNIVERSAL)
|
||||
cons.infinite_length = true
|
||||
expected = %w{ 24 80 24 80 04 01 01 00 00 24 80 04 01 02 00 00 04 01 03 00 00 }
|
||||
raw = [expected.join('')].pack('H*')
|
||||
assert_equal(raw, cons.to_der)
|
||||
assert_equal(raw, OpenSSL::ASN1.decode(raw).to_der)
|
||||
end
|
||||
octets = [ container1, container2, octets3,
|
||||
OpenSSL::ASN1::EndOfContent.new() ]
|
||||
cons = OpenSSL::ASN1::Constructive.new(octets, OpenSSL::ASN1::OCTET_STRING, nil, :UNIVERSAL)
|
||||
cons.infinite_length = true
|
||||
expected = %w{ 24 80 24 80 04 01 01 00 00 24 80 04 01 02 00 00 04 01 03 00 00 }
|
||||
raw = [expected.join('')].pack('H*')
|
||||
assert_equal(raw, cons.to_der)
|
||||
assert_equal(raw, OpenSSL::ASN1.decode(raw).to_der)
|
||||
end
|
||||
|
||||
def test_bit_string_infinite_length
|
||||
begin
|
||||
content = [ OpenSSL::ASN1::BitString.new("\x01"),
|
||||
OpenSSL::ASN1::EndOfContent.new() ]
|
||||
cons = OpenSSL::ASN1::Constructive.new(
|
||||
content,
|
||||
OpenSSL::ASN1::BIT_STRING,
|
||||
nil,
|
||||
:UNIVERSAL)
|
||||
cons.infinite_length = true
|
||||
expected = %w{ 23 80 03 02 00 01 00 00 }
|
||||
raw = [expected.join('')].pack('H*')
|
||||
assert_equal(raw, cons.to_der)
|
||||
assert_equal(raw, OpenSSL::ASN1.decode(raw).to_der)
|
||||
end
|
||||
content = [ OpenSSL::ASN1::BitString.new("\x01"),
|
||||
OpenSSL::ASN1::EndOfContent.new() ]
|
||||
cons = OpenSSL::ASN1::Constructive.new(content, OpenSSL::ASN1::BIT_STRING, nil, :UNIVERSAL)
|
||||
cons.infinite_length = true
|
||||
expected = %w{ 23 80 03 02 00 01 00 00 }
|
||||
raw = [expected.join('')].pack('H*')
|
||||
assert_equal(raw, cons.to_der)
|
||||
assert_equal(raw, OpenSSL::ASN1.decode(raw).to_der)
|
||||
end
|
||||
|
||||
def test_primitive_inf_length
|
||||
|
@ -610,6 +535,29 @@ rEzBQ0F9dUyqQ9gyRg8KHhDfv9HzT1d/rnUZMkoombwYBRIUChGCYV0GnJcan2Zm
|
|||
assert_equal(false, asn1.value[3].infinite_length)
|
||||
end
|
||||
|
||||
def test_decode_constructed_overread
|
||||
test = %w{ 31 06 31 02 30 02 05 00 }
|
||||
# ^ <- invalid
|
||||
raw = [test.join].pack("H*")
|
||||
ret = []
|
||||
assert_raise(OpenSSL::ASN1::ASN1Error) {
|
||||
OpenSSL::ASN1.traverse(raw) { |x| ret << x }
|
||||
}
|
||||
assert_equal 2, ret.size
|
||||
assert_equal 17, ret[0][6]
|
||||
assert_equal 17, ret[1][6]
|
||||
|
||||
test = %w{ 31 80 30 03 00 00 }
|
||||
# ^ <- invalid
|
||||
raw = [test.join].pack("H*")
|
||||
ret = []
|
||||
assert_raise(OpenSSL::ASN1::ASN1Error) {
|
||||
OpenSSL::ASN1.traverse(raw) { |x| ret << x }
|
||||
}
|
||||
assert_equal 1, ret.size
|
||||
assert_equal 17, ret[0][6]
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def assert_universal(tag, asn1)
|
||||
|
@ -621,4 +569,3 @@ rEzBQ0F9dUyqQ9gyRg8KHhDfv9HzT1d/rnUZMkoombwYBRIUChGCYV0GnJcan2Zm
|
|||
end
|
||||
|
||||
end if defined?(OpenSSL::TestUtils)
|
||||
|
||||
|
|
|
@ -4,110 +4,131 @@ require_relative 'utils'
|
|||
if defined?(OpenSSL::TestUtils)
|
||||
|
||||
class OpenSSL::TestCipher < OpenSSL::TestCase
|
||||
|
||||
@ciphers = OpenSSL::Cipher.ciphers
|
||||
|
||||
class << self
|
||||
|
||||
module Helper
|
||||
def has_cipher?(name)
|
||||
@ciphers ||= OpenSSL::Cipher.ciphers
|
||||
@ciphers.include?(name)
|
||||
end
|
||||
end
|
||||
include Helper
|
||||
extend Helper
|
||||
|
||||
def has_ciphers?(list)
|
||||
list.all? { |name| has_cipher?(name) }
|
||||
end
|
||||
|
||||
def test_encrypt_decrypt
|
||||
# NIST SP 800-38A F.2.1
|
||||
key = ["2b7e151628aed2a6abf7158809cf4f3c"].pack("H*")
|
||||
iv = ["000102030405060708090a0b0c0d0e0f"].pack("H*")
|
||||
pt = ["6bc1bee22e409f96e93d7e117393172a" \
|
||||
"ae2d8a571e03ac9c9eb76fac45af8e51"].pack("H*")
|
||||
ct = ["7649abac8119b246cee98e9b12e9197d" \
|
||||
"5086cb9b507219ee95db113a917678b2"].pack("H*")
|
||||
cipher = new_encryptor("aes-128-cbc", key: key, iv: iv, padding: 0)
|
||||
assert_equal ct, cipher.update(pt) << cipher.final
|
||||
cipher = new_decryptor("aes-128-cbc", key: key, iv: iv, padding: 0)
|
||||
assert_equal pt, cipher.update(ct) << cipher.final
|
||||
end
|
||||
|
||||
def setup
|
||||
@c1 = OpenSSL::Cipher.new("DES-EDE3-CBC")
|
||||
@c2 = OpenSSL::Cipher::DES.new(:EDE3, "CBC")
|
||||
@key = "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
|
||||
@iv = "\0\0\0\0\0\0\0\0"
|
||||
@hexkey = "0000000000000000000000000000000000000000000000"
|
||||
@hexiv = "0000000000000000"
|
||||
@data = "DATA"
|
||||
end
|
||||
def test_pkcs5_keyivgen
|
||||
pass = "\x00" * 8
|
||||
salt = "\x01" * 8
|
||||
num = 2048
|
||||
pt = "data to be encrypted"
|
||||
cipher = OpenSSL::Cipher.new("DES-EDE3-CBC").encrypt
|
||||
cipher.pkcs5_keyivgen(pass, salt, num, "MD5")
|
||||
s1 = cipher.update(pt) << cipher.final
|
||||
|
||||
def teardown
|
||||
super
|
||||
@c1 = @c2 = nil
|
||||
end
|
||||
d1 = num.times.inject(pass + salt) {|out, _| OpenSSL::Digest::MD5.digest(out) }
|
||||
d2 = num.times.inject(d1 + pass + salt) {|out, _| OpenSSL::Digest::MD5.digest(out) }
|
||||
key = (d1 + d2)[0, 24]
|
||||
iv = (d1 + d2)[24, 8]
|
||||
cipher = new_encryptor("DES-EDE3-CBC", key: key, iv: iv)
|
||||
s2 = cipher.update(pt) << cipher.final
|
||||
|
||||
def test_crypt
|
||||
@c1.encrypt.pkcs5_keyivgen(@key, @iv)
|
||||
@c2.encrypt.pkcs5_keyivgen(@key, @iv)
|
||||
s1 = @c1.update(@data) + @c1.final
|
||||
s2 = @c2.update(@data) + @c2.final
|
||||
assert_equal(s1, s2, "encrypt")
|
||||
|
||||
@c1.decrypt.pkcs5_keyivgen(@key, @iv)
|
||||
@c2.decrypt.pkcs5_keyivgen(@key, @iv)
|
||||
assert_equal(@data, @c1.update(s1)+@c1.final, "decrypt")
|
||||
assert_equal(@data, @c2.update(s2)+@c2.final, "decrypt")
|
||||
assert_equal s1, s2
|
||||
end
|
||||
|
||||
def test_info
|
||||
assert_equal("DES-EDE3-CBC", @c1.name, "name")
|
||||
assert_equal("DES-EDE3-CBC", @c2.name, "name")
|
||||
assert_kind_of(Integer, @c1.key_len, "key_len")
|
||||
assert_kind_of(Integer, @c1.iv_len, "iv_len")
|
||||
cipher = OpenSSL::Cipher.new("DES-EDE3-CBC").encrypt
|
||||
assert_equal "DES-EDE3-CBC", cipher.name
|
||||
assert_equal 24, cipher.key_len
|
||||
assert_equal 8, cipher.iv_len
|
||||
end
|
||||
|
||||
def test_dup
|
||||
assert_equal(@c1.name, @c1.dup.name, "dup")
|
||||
assert_equal(@c1.name, @c1.clone.name, "clone")
|
||||
@c1.encrypt
|
||||
@c1.key = @key
|
||||
@c1.iv = @iv
|
||||
tmpc = @c1.dup
|
||||
s1 = @c1.update(@data) + @c1.final
|
||||
s2 = tmpc.update(@data) + tmpc.final
|
||||
cipher = OpenSSL::Cipher.new("aes-128-cbc").encrypt
|
||||
assert_equal cipher.name, cipher.dup.name
|
||||
cipher.encrypt
|
||||
cipher.random_key
|
||||
cipher.random_iv
|
||||
tmpc = cipher.dup
|
||||
s1 = cipher.update("data") + cipher.final
|
||||
s2 = tmpc.update("data") + tmpc.final
|
||||
assert_equal(s1, s2, "encrypt dup")
|
||||
end
|
||||
|
||||
def test_reset
|
||||
@c1.encrypt
|
||||
@c1.key = @key
|
||||
@c1.iv = @iv
|
||||
s1 = @c1.update(@data) + @c1.final
|
||||
@c1.reset
|
||||
s2 = @c1.update(@data) + @c1.final
|
||||
cipher = OpenSSL::Cipher.new("aes-128-cbc").encrypt
|
||||
cipher.encrypt
|
||||
cipher.random_key
|
||||
cipher.random_iv
|
||||
s1 = cipher.update("data") + cipher.final
|
||||
cipher.reset
|
||||
s2 = cipher.update("data") + cipher.final
|
||||
assert_equal(s1, s2, "encrypt reset")
|
||||
end
|
||||
|
||||
def test_key_iv_set
|
||||
# default value for DES-EDE3-CBC
|
||||
assert_equal(24, @c1.key_len)
|
||||
assert_equal(8, @c1.iv_len)
|
||||
assert_raise(ArgumentError) { @c1.key = "\x01" * 23 }
|
||||
@c1.key = "\x01" * 24
|
||||
assert_raise(ArgumentError) { @c1.key = "\x01" * 25 }
|
||||
assert_raise(ArgumentError) { @c1.iv = "\x01" * 7 }
|
||||
@c1.iv = "\x01" * 8
|
||||
assert_raise(ArgumentError) { @c1.iv = "\x01" * 9 }
|
||||
cipher = OpenSSL::Cipher.new("DES-EDE3-CBC").encrypt
|
||||
assert_raise(ArgumentError) { cipher.key = "\x01" * 23 }
|
||||
assert_nothing_raised { cipher.key = "\x01" * 24 }
|
||||
assert_raise(ArgumentError) { cipher.key = "\x01" * 25 }
|
||||
assert_raise(ArgumentError) { cipher.iv = "\x01" * 7 }
|
||||
assert_nothing_raised { cipher.iv = "\x01" * 8 }
|
||||
assert_raise(ArgumentError) { cipher.iv = "\x01" * 9 }
|
||||
end
|
||||
|
||||
def test_random_key_iv
|
||||
data = "data"
|
||||
s1, s2 = 2.times.map do
|
||||
cipher = OpenSSL::Cipher.new("aes-128-cbc").encrypt
|
||||
cipher.random_key
|
||||
cipher.iv = "\x01" * 16
|
||||
cipher.update(data) << cipher.final
|
||||
end
|
||||
assert_not_equal s1, s2
|
||||
|
||||
s1, s2 = 2.times.map do
|
||||
cipher = OpenSSL::Cipher.new("aes-128-cbc").encrypt
|
||||
cipher.key = "\x01" * 16
|
||||
cipher.random_iv
|
||||
cipher.update(data) << cipher.final
|
||||
end
|
||||
assert_not_equal s1, s2
|
||||
end
|
||||
|
||||
def test_empty_data
|
||||
@c1.encrypt
|
||||
assert_raise(ArgumentError){ @c1.update("") }
|
||||
cipher = OpenSSL::Cipher.new("DES-EDE3-CBC").encrypt
|
||||
cipher.random_key
|
||||
assert_raise(ArgumentError) { cipher.update("") }
|
||||
end
|
||||
|
||||
def test_initialize
|
||||
assert_raise(RuntimeError) {@c1.__send__(:initialize, "DES-EDE3-CBC")}
|
||||
assert_raise(RuntimeError) {OpenSSL::Cipher.allocate.final}
|
||||
cipher = OpenSSL::Cipher.new("DES-EDE3-CBC")
|
||||
assert_raise(RuntimeError) { cipher.__send__(:initialize, "DES-EDE3-CBC") }
|
||||
assert_raise(RuntimeError) { OpenSSL::Cipher.allocate.final }
|
||||
end
|
||||
|
||||
def test_ctr_if_exists
|
||||
begin
|
||||
cipher = OpenSSL::Cipher.new('aes-128-ctr')
|
||||
cipher.encrypt
|
||||
cipher.pkcs5_keyivgen('password')
|
||||
c = cipher.update('hello,world') + cipher.final
|
||||
cipher.decrypt
|
||||
cipher.pkcs5_keyivgen('password')
|
||||
assert_equal('hello,world', cipher.update(c) + cipher.final)
|
||||
end
|
||||
# NIST SP 800-38A F.5.1
|
||||
key = ["2b7e151628aed2a6abf7158809cf4f3c"].pack("H*")
|
||||
iv = ["f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff"].pack("H*")
|
||||
pt = ["6bc1bee22e409f96e93d7e117393172a" \
|
||||
"ae2d8a571e03ac9c9eb76fac45af8e51"].pack("H*")
|
||||
ct = ["874d6191b620e3261bef6864990db6ce" \
|
||||
"9806f66b7970fdff8617187bb9fffdff"].pack("H*")
|
||||
cipher = new_encryptor("aes-128-ctr", key: key, iv: iv, padding: 0)
|
||||
assert_equal ct, cipher.update(pt) << cipher.final
|
||||
cipher = new_decryptor("aes-128-ctr", key: key, iv: iv, padding: 0)
|
||||
assert_equal pt, cipher.update(ct) << cipher.final
|
||||
end if has_cipher?('aes-128-ctr')
|
||||
|
||||
def test_ciphers
|
||||
|
@ -136,202 +157,159 @@ class OpenSSL::TestCipher < OpenSSL::TestCase
|
|||
}
|
||||
end
|
||||
|
||||
def test_AES_crush
|
||||
500.times do
|
||||
assert_nothing_raised("[Bug #2768]") do
|
||||
# it caused OpenSSL SEGV by uninitialized key
|
||||
OpenSSL::Cipher::AES128.new("ECB").update "." * 17
|
||||
end
|
||||
def test_update_raise_if_key_not_set
|
||||
assert_raise(OpenSSL::Cipher::CipherError) do
|
||||
# it caused OpenSSL SEGV by uninitialized key [Bug #2768]
|
||||
OpenSSL::Cipher::AES128.new("ECB").update "." * 17
|
||||
end
|
||||
end
|
||||
|
||||
if has_ciphers?(['aes-128-gcm', 'aes-192-gcm', 'aes-256-gcm'])
|
||||
|
||||
def test_authenticated
|
||||
def test_authenticated
|
||||
if has_cipher?('aes-128-gcm')
|
||||
cipher = OpenSSL::Cipher.new('aes-128-gcm')
|
||||
assert_predicate(cipher, :authenticated?)
|
||||
cipher = OpenSSL::Cipher.new('aes-128-cbc')
|
||||
assert_not_predicate(cipher, :authenticated?)
|
||||
end
|
||||
|
||||
def test_aes_gcm
|
||||
['aes-128-gcm', 'aes-192-gcm', 'aes-256-gcm'].each do |algo|
|
||||
pt = "You should all use Authenticated Encryption!"
|
||||
cipher, key, iv = new_encryptor(algo)
|
||||
|
||||
cipher.auth_data = "aad"
|
||||
ct = cipher.update(pt) + cipher.final
|
||||
tag = cipher.auth_tag
|
||||
assert_equal(16, tag.size)
|
||||
|
||||
decipher = new_decryptor(algo, key, iv)
|
||||
decipher.auth_tag = tag
|
||||
decipher.auth_data = "aad"
|
||||
|
||||
assert_equal(pt, decipher.update(ct) + decipher.final)
|
||||
end
|
||||
end
|
||||
|
||||
def test_aes_gcm_short_tag
|
||||
['aes-128-gcm', 'aes-192-gcm', 'aes-256-gcm'].each do |algo|
|
||||
pt = "You should all use Authenticated Encryption!"
|
||||
cipher, key, iv = new_encryptor(algo)
|
||||
|
||||
cipher.auth_data = "aad"
|
||||
ct = cipher.update(pt) + cipher.final
|
||||
tag = cipher.auth_tag(8)
|
||||
assert_equal(8, tag.size)
|
||||
|
||||
decipher = new_decryptor(algo, key, iv)
|
||||
decipher.auth_tag = tag
|
||||
decipher.auth_data = "aad"
|
||||
|
||||
assert_equal(pt, decipher.update(ct) + decipher.final)
|
||||
end
|
||||
end
|
||||
|
||||
def test_aes_gcm_wrong_tag
|
||||
pt = "You should all use Authenticated Encryption!"
|
||||
cipher, key, iv = new_encryptor('aes-128-gcm')
|
||||
|
||||
cipher.auth_data = "aad"
|
||||
ct = cipher.update(pt) + cipher.final
|
||||
tag = cipher.auth_tag
|
||||
|
||||
decipher = new_decryptor('aes-128-gcm', key, iv)
|
||||
tag.setbyte(-1, (tag.getbyte(-1) + 1) & 0xff)
|
||||
decipher.auth_tag = tag
|
||||
decipher.auth_data = "aad"
|
||||
|
||||
assert_raise OpenSSL::Cipher::CipherError do
|
||||
decipher.update(ct) + decipher.final
|
||||
end
|
||||
end
|
||||
|
||||
def test_aes_gcm_wrong_auth_data
|
||||
pt = "You should all use Authenticated Encryption!"
|
||||
cipher, key, iv = new_encryptor('aes-128-gcm')
|
||||
|
||||
cipher.auth_data = "aad"
|
||||
ct = cipher.update(pt) + cipher.final
|
||||
tag = cipher.auth_tag
|
||||
|
||||
decipher = new_decryptor('aes-128-gcm', key, iv)
|
||||
decipher.auth_tag = tag
|
||||
decipher.auth_data = "daa"
|
||||
|
||||
assert_raise OpenSSL::Cipher::CipherError do
|
||||
decipher.update(ct) + decipher.final
|
||||
end
|
||||
end
|
||||
|
||||
def test_aes_gcm_wrong_ciphertext
|
||||
pt = "You should all use Authenticated Encryption!"
|
||||
cipher, key, iv = new_encryptor('aes-128-gcm')
|
||||
|
||||
cipher.auth_data = "aad"
|
||||
ct = cipher.update(pt) + cipher.final
|
||||
tag = cipher.auth_tag
|
||||
|
||||
decipher = new_decryptor('aes-128-gcm', key, iv)
|
||||
decipher.auth_tag = tag
|
||||
decipher.auth_data = "aad"
|
||||
|
||||
assert_raise OpenSSL::Cipher::CipherError do
|
||||
decipher.update(ct[0..-2] << ct[-1].succ) + decipher.final
|
||||
end
|
||||
end
|
||||
|
||||
def test_aes_gcm_variable_iv_len
|
||||
pt = "You should all use Authenticated Encryption!"
|
||||
cipher = OpenSSL::Cipher.new("aes-128-gcm").encrypt
|
||||
cipher.key = "x" * 16
|
||||
assert_equal(12, cipher.iv_len)
|
||||
cipher.iv = "a" * 12
|
||||
ct1 = cipher.update(pt) << cipher.final
|
||||
tag1 = cipher.auth_tag
|
||||
|
||||
cipher = OpenSSL::Cipher.new("aes-128-gcm").encrypt
|
||||
cipher.key = "x" * 16
|
||||
cipher.iv_len = 10
|
||||
assert_equal(10, cipher.iv_len)
|
||||
cipher.iv = "a" * 10
|
||||
ct2 = cipher.update(pt) << cipher.final
|
||||
tag2 = cipher.auth_tag
|
||||
|
||||
assert_not_equal ct1, ct2
|
||||
assert_not_equal tag1, tag2
|
||||
|
||||
decipher = OpenSSL::Cipher.new("aes-128-gcm").decrypt
|
||||
decipher.auth_tag = tag1
|
||||
decipher.key = "x" * 16
|
||||
decipher.iv_len = 12
|
||||
decipher.iv = "a" * 12
|
||||
assert_equal(pt, decipher.update(ct1) << decipher.final)
|
||||
|
||||
decipher.reset
|
||||
decipher.auth_tag = tag2
|
||||
assert_raise(OpenSSL::Cipher::CipherError) {
|
||||
decipher.update(ct2) << decipher.final
|
||||
}
|
||||
|
||||
decipher.reset
|
||||
decipher.auth_tag = tag2
|
||||
decipher.iv_len = 10
|
||||
decipher.iv = "a" * 10
|
||||
assert_equal(pt, decipher.update(ct2) << decipher.final)
|
||||
end
|
||||
|
||||
cipher = OpenSSL::Cipher.new('aes-128-cbc')
|
||||
assert_not_predicate(cipher, :authenticated?)
|
||||
end
|
||||
|
||||
def test_aes_gcm
|
||||
# GCM spec Appendix B Test Case 4
|
||||
key = ["feffe9928665731c6d6a8f9467308308"].pack("H*")
|
||||
iv = ["cafebabefacedbaddecaf888"].pack("H*")
|
||||
aad = ["feedfacedeadbeeffeedfacedeadbeef" \
|
||||
"abaddad2"].pack("H*")
|
||||
pt = ["d9313225f88406e5a55909c5aff5269a" \
|
||||
"86a7a9531534f7da2e4c303d8a318a72" \
|
||||
"1c3c0c95956809532fcf0e2449a6b525" \
|
||||
"b16aedf5aa0de657ba637b39"].pack("H*")
|
||||
ct = ["42831ec2217774244b7221b784d0d49c" \
|
||||
"e3aa212f2c02a4e035c17e2329aca12e" \
|
||||
"21d514b25466931c7d8f6a5aac84aa05" \
|
||||
"1ba30b396a0aac973d58e091"].pack("H*")
|
||||
tag = ["5bc94fbc3221a5db94fae95ae7121a47"].pack("H*")
|
||||
|
||||
cipher = new_encryptor("aes-128-gcm", key: key, iv: iv, auth_data: aad)
|
||||
assert_equal ct, cipher.update(pt) << cipher.final
|
||||
assert_equal tag, cipher.auth_tag
|
||||
cipher = new_decryptor("aes-128-gcm", key: key, iv: iv, auth_data: aad, auth_tag: tag)
|
||||
assert_equal pt, cipher.update(ct) << cipher.final
|
||||
|
||||
# truncated tag is accepted
|
||||
cipher = new_encryptor("aes-128-gcm", key: key, iv: iv, auth_data: aad)
|
||||
assert_equal ct, cipher.update(pt) << cipher.final
|
||||
assert_equal tag[0, 8], cipher.auth_tag(8)
|
||||
cipher = new_decryptor("aes-128-gcm", key: key, iv: iv, auth_data: aad, auth_tag: tag[0, 8])
|
||||
assert_equal pt, cipher.update(ct) << cipher.final
|
||||
|
||||
# wrong tag is rejected
|
||||
tag2 = tag.dup
|
||||
tag2.setbyte(-1, (tag2.getbyte(-1) + 1) & 0xff)
|
||||
cipher = new_decryptor("aes-128-gcm", key: key, iv: iv, auth_data: aad, auth_tag: tag2)
|
||||
cipher.update(ct)
|
||||
assert_raise(OpenSSL::Cipher::CipherError) { cipher.final }
|
||||
|
||||
# wrong aad is rejected
|
||||
aad2 = aad[0..-2] << aad[-1].succ
|
||||
cipher = new_decryptor("aes-128-gcm", key: key, iv: iv, auth_data: aad2, auth_tag: tag)
|
||||
cipher.update(ct)
|
||||
assert_raise(OpenSSL::Cipher::CipherError) { cipher.final }
|
||||
|
||||
# wrong ciphertext is rejected
|
||||
ct2 = ct[0..-2] << ct[-1].succ
|
||||
cipher = new_decryptor("aes-128-gcm", key: key, iv: iv, auth_data: aad, auth_tag: tag)
|
||||
cipher.update(ct2)
|
||||
assert_raise(OpenSSL::Cipher::CipherError) { cipher.final }
|
||||
end if has_cipher?("aes-128-gcm")
|
||||
|
||||
def test_aes_gcm_variable_iv_len
|
||||
# GCM spec Appendix B Test Case 5
|
||||
key = ["feffe9928665731c6d6a8f9467308308"].pack("H*")
|
||||
iv = ["cafebabefacedbad"].pack("H*")
|
||||
aad = ["feedfacedeadbeeffeedfacedeadbeef" \
|
||||
"abaddad2"].pack("H*")
|
||||
pt = ["d9313225f88406e5a55909c5aff5269a" \
|
||||
"86a7a9531534f7da2e4c303d8a318a72" \
|
||||
"1c3c0c95956809532fcf0e2449a6b525" \
|
||||
"b16aedf5aa0de657ba637b39"].pack("H*")
|
||||
ct = ["61353b4c2806934a777ff51fa22a4755" \
|
||||
"699b2a714fcdc6f83766e5f97b6c7423" \
|
||||
"73806900e49f24b22b097544d4896b42" \
|
||||
"4989b5e1ebac0f07c23f4598"].pack("H*")
|
||||
tag = ["3612d2e79e3b0785561be14aaca2fccb"].pack("H*")
|
||||
|
||||
cipher = new_encryptor("aes-128-gcm", key: key, iv_len: 8, iv: iv, auth_data: aad)
|
||||
assert_equal ct, cipher.update(pt) << cipher.final
|
||||
assert_equal tag, cipher.auth_tag
|
||||
cipher = new_decryptor("aes-128-gcm", key: key, iv_len: 8, iv: iv, auth_data: aad, auth_tag: tag)
|
||||
assert_equal pt, cipher.update(ct) << cipher.final
|
||||
end if has_cipher?("aes-128-gcm")
|
||||
|
||||
def test_aes_ocb_tag_len
|
||||
pt = "You should all use Authenticated Encryption!"
|
||||
cipher = OpenSSL::Cipher.new("aes-128-ocb").encrypt
|
||||
cipher.auth_tag_len = 14
|
||||
cipher.iv_len = 8
|
||||
key = cipher.random_key
|
||||
iv = cipher.random_iv
|
||||
cipher.auth_data = "aad"
|
||||
ct = cipher.update(pt) + cipher.final
|
||||
tag = cipher.auth_tag
|
||||
assert_equal(14, tag.size)
|
||||
# RFC 7253 Appendix A; the second sample
|
||||
key = ["000102030405060708090A0B0C0D0E0F"].pack("H*")
|
||||
iv = ["BBAA99887766554433221101"].pack("H*")
|
||||
aad = ["0001020304050607"].pack("H*")
|
||||
pt = ["0001020304050607"].pack("H*")
|
||||
ct = ["6820B3657B6F615A"].pack("H*")
|
||||
tag = ["5725BDA0D3B4EB3A257C9AF1F8F03009"].pack("H*")
|
||||
|
||||
decipher = OpenSSL::Cipher.new("aes-128-ocb").decrypt
|
||||
decipher.auth_tag_len = 14
|
||||
decipher.auth_tag = tag
|
||||
decipher.iv_len = 8
|
||||
decipher.key = key
|
||||
decipher.iv = iv
|
||||
decipher.auth_data = "aad"
|
||||
assert_equal(pt, decipher.update(ct) + decipher.final)
|
||||
cipher = new_encryptor("aes-128-ocb", key: key, iv: iv, auth_data: aad)
|
||||
assert_equal ct, cipher.update(pt) << cipher.final
|
||||
assert_equal tag, cipher.auth_tag
|
||||
cipher = new_decryptor("aes-128-ocb", key: key, iv: iv, auth_data: aad, auth_tag: tag)
|
||||
assert_equal pt, cipher.update(ct) << cipher.final
|
||||
|
||||
# RFC 7253 Appendix A; with 96 bits tag length
|
||||
key = ["0F0E0D0C0B0A09080706050403020100"].pack("H*")
|
||||
iv = ["BBAA9988776655443322110D"].pack("H*")
|
||||
aad = ["000102030405060708090A0B0C0D0E0F1011121314151617" \
|
||||
"18191A1B1C1D1E1F2021222324252627"].pack("H*")
|
||||
pt = ["000102030405060708090A0B0C0D0E0F1011121314151617" \
|
||||
"18191A1B1C1D1E1F2021222324252627"].pack("H*")
|
||||
ct = ["1792A4E31E0755FB03E31B22116E6C2DDF9EFD6E33D536F1" \
|
||||
"A0124B0A55BAE884ED93481529C76B6A"].pack("H*")
|
||||
tag = ["D0C515F4D1CDD4FDAC4F02AA"].pack("H*")
|
||||
|
||||
cipher = new_encryptor("aes-128-ocb", auth_tag_len: 12, key: key, iv: iv, auth_data: aad)
|
||||
assert_equal ct, cipher.update(pt) << cipher.final
|
||||
assert_equal tag, cipher.auth_tag
|
||||
cipher = new_decryptor("aes-128-ocb", auth_tag_len: 12, key: key, iv: iv, auth_data: aad, auth_tag: tag)
|
||||
assert_equal pt, cipher.update(ct) << cipher.final
|
||||
|
||||
decipher = OpenSSL::Cipher.new("aes-128-ocb").decrypt
|
||||
decipher.auth_tag_len = 9
|
||||
decipher.auth_tag = tag[0, 9]
|
||||
decipher.iv_len = 8
|
||||
decipher.key = key
|
||||
decipher.iv = iv
|
||||
decipher.auth_data = "aad"
|
||||
assert_raise(OpenSSL::Cipher::CipherError) {
|
||||
decipher.update(ct) + decipher.final
|
||||
}
|
||||
end if has_cipher?("aes-128-ocb")
|
||||
|
||||
def test_aes_gcm_key_iv_order_issue
|
||||
pt = "[ruby/openssl#49]"
|
||||
cipher = OpenSSL::Cipher.new("aes-128-gcm").encrypt
|
||||
cipher.key = "x" * 16
|
||||
cipher.iv = "a" * 12
|
||||
ct1 = cipher.update(pt) << cipher.final
|
||||
tag1 = cipher.auth_tag
|
||||
|
||||
cipher = OpenSSL::Cipher.new("aes-128-gcm").encrypt
|
||||
cipher.iv = "a" * 12
|
||||
cipher.key = "x" * 16
|
||||
ct2 = cipher.update(pt) << cipher.final
|
||||
tag2 = cipher.auth_tag
|
||||
|
||||
assert_equal ct1, ct2
|
||||
assert_equal tag1, tag2
|
||||
end if has_cipher?("aes-128-gcm")
|
||||
|
||||
private
|
||||
|
||||
def new_encryptor(algo)
|
||||
cipher = OpenSSL::Cipher.new(algo)
|
||||
cipher.encrypt
|
||||
key = cipher.random_key
|
||||
iv = cipher.random_iv
|
||||
[cipher, key, iv]
|
||||
def new_encryptor(algo, **kwargs)
|
||||
OpenSSL::Cipher.new(algo).tap do |cipher|
|
||||
cipher.encrypt
|
||||
kwargs.each {|k, v| cipher.send(:"#{k}=", v) }
|
||||
end
|
||||
end
|
||||
|
||||
def new_decryptor(algo, key, iv)
|
||||
def new_decryptor(algo, **kwargs)
|
||||
OpenSSL::Cipher.new(algo).tap do |cipher|
|
||||
cipher.decrypt
|
||||
cipher.key = key
|
||||
cipher.iv = iv
|
||||
kwargs.each {|k, v| cipher.send(:"#{k}=", v) }
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -7,27 +7,21 @@ class OpenSSL::TestDigest < OpenSSL::TestCase
|
|||
def setup
|
||||
@d1 = OpenSSL::Digest.new("MD5")
|
||||
@d2 = OpenSSL::Digest::MD5.new
|
||||
@md = Digest::MD5.new
|
||||
@data = "DATA"
|
||||
end
|
||||
|
||||
def teardown
|
||||
super
|
||||
@d1 = @d2 = @md = nil
|
||||
end
|
||||
|
||||
def test_digest
|
||||
assert_equal(@md.digest, @d1.digest)
|
||||
assert_equal(@md.hexdigest, @d1.hexdigest)
|
||||
@d1 << @data
|
||||
@d2 << @data
|
||||
@md << @data
|
||||
assert_equal(@md.digest, @d1.digest)
|
||||
assert_equal(@md.hexdigest, @d1.hexdigest)
|
||||
assert_equal(@d1.digest, @d2.digest)
|
||||
assert_equal(@d1.hexdigest, @d2.hexdigest)
|
||||
assert_equal(@md.digest, OpenSSL::Digest::MD5.digest(@data))
|
||||
assert_equal(@md.hexdigest, OpenSSL::Digest::MD5.hexdigest(@data))
|
||||
null_hex = "d41d8cd98f00b204e9800998ecf8427e"
|
||||
null_bin = [null_hex].pack("H*")
|
||||
data = "DATA"
|
||||
hex = "e44f9e348e41cb272efa87387728571b"
|
||||
bin = [hex].pack("H*")
|
||||
assert_equal(null_bin, @d1.digest)
|
||||
assert_equal(null_hex, @d1.hexdigest)
|
||||
@d1 << data
|
||||
assert_equal(bin, @d1.digest)
|
||||
assert_equal(hex, @d1.hexdigest)
|
||||
assert_equal(bin, OpenSSL::Digest::MD5.digest(data))
|
||||
assert_equal(hex, OpenSSL::Digest::MD5.hexdigest(data))
|
||||
end
|
||||
|
||||
def test_eql
|
||||
|
@ -43,17 +37,17 @@ class OpenSSL::TestDigest < OpenSSL::TestCase
|
|||
end
|
||||
|
||||
def test_dup
|
||||
@d1.update(@data)
|
||||
@d1.update("DATA")
|
||||
assert_equal(@d1.name, @d1.dup.name, "dup")
|
||||
assert_equal(@d1.name, @d1.clone.name, "clone")
|
||||
assert_equal(@d1.digest, @d1.clone.digest, "clone .digest")
|
||||
end
|
||||
|
||||
def test_reset
|
||||
@d1.update(@data)
|
||||
@d1.update("DATA")
|
||||
dig1 = @d1.digest
|
||||
@d1.reset
|
||||
@d1.update(@data)
|
||||
@d1.update("DATA")
|
||||
dig2 = @d1.digest
|
||||
assert_equal(dig1, dig2, "reset")
|
||||
end
|
||||
|
|
|
@ -72,13 +72,6 @@ class OpenSSL::TestEngine < OpenSSL::TestCase
|
|||
end;
|
||||
end
|
||||
|
||||
def test_dup
|
||||
with_openssl <<-'end;'
|
||||
engine = get_engine
|
||||
assert_raise(NoMethodError) { engine.dup }
|
||||
end;
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
# this is required because OpenSSL::Engine methods change global state
|
||||
|
|
|
@ -1,33 +1,26 @@
|
|||
# coding: UTF-8
|
||||
# frozen_string_literal: false
|
||||
|
||||
require_relative 'utils'
|
||||
|
||||
class OpenSSL::TestHMAC < OpenSSL::TestCase
|
||||
def setup
|
||||
@digest = OpenSSL::Digest::MD5
|
||||
@key = "KEY"
|
||||
@data = "DATA"
|
||||
@h1 = OpenSSL::HMAC.new(@key, @digest.new)
|
||||
@h2 = OpenSSL::HMAC.new(@key, "MD5")
|
||||
end
|
||||
|
||||
def test_hmac
|
||||
@h1.update(@data)
|
||||
@h2.update(@data)
|
||||
assert_equal(@h1.digest, @h2.digest)
|
||||
# RFC 2202 2. Test Cases for HMAC-MD5
|
||||
hmac = OpenSSL::HMAC.new(["0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b"].pack("H*"), "MD5")
|
||||
hmac.update("Hi There")
|
||||
assert_equal ["9294727a3638bb1c13f48ef8158bfc9d"].pack("H*"), hmac.digest
|
||||
assert_equal "9294727a3638bb1c13f48ef8158bfc9d", hmac.hexdigest
|
||||
|
||||
assert_equal(OpenSSL::HMAC.digest(@digest.new, @key, @data), @h1.digest, "digest")
|
||||
assert_equal(OpenSSL::HMAC.hexdigest(@digest.new, @key, @data), @h1.hexdigest, "hexdigest")
|
||||
|
||||
assert_equal(OpenSSL::HMAC.digest("MD5", @key, @data), @h2.digest, "digest")
|
||||
assert_equal(OpenSSL::HMAC.hexdigest("MD5", @key, @data), @h2.hexdigest, "hexdigest")
|
||||
# RFC 4231 4.2. Test Case 1
|
||||
hmac = OpenSSL::HMAC.new(["0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b"].pack("H*"), "SHA224")
|
||||
hmac.update("Hi There")
|
||||
assert_equal ["896fb1128abbdf196832107cd49df33f47b4b1169912ba4f53684b22"].pack("H*"), hmac.digest
|
||||
assert_equal "896fb1128abbdf196832107cd49df33f47b4b1169912ba4f53684b22", hmac.hexdigest
|
||||
end
|
||||
|
||||
def test_dup
|
||||
@h1.update(@data)
|
||||
h = @h1.dup
|
||||
assert_equal(@h1.digest, h.digest, "dup digest")
|
||||
h1 = OpenSSL::HMAC.new("KEY", "MD5")
|
||||
h1.update("DATA")
|
||||
h = h1.dup
|
||||
assert_equal(h1.digest, h.digest, "dup digest")
|
||||
end
|
||||
|
||||
def test_binary_update
|
||||
|
@ -38,9 +31,10 @@ class OpenSSL::TestHMAC < OpenSSL::TestCase
|
|||
end
|
||||
|
||||
def test_reset_keep_key
|
||||
first = @h1.update("test").hexdigest
|
||||
@h2.reset
|
||||
second = @h2.update("test").hexdigest
|
||||
h1 = OpenSSL::HMAC.new("KEY", "MD5")
|
||||
first = h1.update("test").hexdigest
|
||||
h1.reset
|
||||
second = h1.update("test").hexdigest
|
||||
assert_equal first, second
|
||||
end
|
||||
end if defined?(OpenSSL::TestUtils)
|
||||
|
|
|
@ -5,9 +5,6 @@ if defined?(OpenSSL::TestUtils)
|
|||
|
||||
class OpenSSL::TestOCSP < OpenSSL::TestCase
|
||||
def setup
|
||||
now = Time.at(Time.now.to_i) # suppress usec
|
||||
dgst = OpenSSL::Digest::SHA1.new
|
||||
|
||||
# @ca_cert
|
||||
# |
|
||||
# @cert
|
||||
|
@ -21,7 +18,7 @@ class OpenSSL::TestOCSP < OpenSSL::TestCase
|
|||
["keyUsage", "cRLSign,keyCertSign", true],
|
||||
]
|
||||
@ca_cert = OpenSSL::TestUtils.issue_cert(
|
||||
ca_subj, @ca_key, 1, now, now+3600, ca_exts, nil, nil, dgst)
|
||||
ca_subj, @ca_key, 1, ca_exts, nil, nil)
|
||||
|
||||
cert_subj = OpenSSL::X509::Name.parse("/DC=org/DC=ruby-lang/CN=TestCA2")
|
||||
@cert_key = OpenSSL::TestUtils::TEST_KEY_RSA1024
|
||||
|
@ -30,14 +27,14 @@ class OpenSSL::TestOCSP < OpenSSL::TestCase
|
|||
["keyUsage", "cRLSign,keyCertSign", true],
|
||||
]
|
||||
@cert = OpenSSL::TestUtils.issue_cert(
|
||||
cert_subj, @cert_key, 5, now, now+3600, cert_exts, @ca_cert, @ca_key, dgst)
|
||||
cert_subj, @cert_key, 5, cert_exts, @ca_cert, @ca_key)
|
||||
|
||||
cert2_subj = OpenSSL::X509::Name.parse("/DC=org/DC=ruby-lang/CN=TestCert")
|
||||
@cert2_key = OpenSSL::TestUtils::TEST_KEY_RSA1024
|
||||
cert2_exts = [
|
||||
]
|
||||
@cert2 = OpenSSL::TestUtils.issue_cert(
|
||||
cert2_subj, @cert2_key, 10, now, now+3600, cert2_exts, @cert, @cert_key, dgst)
|
||||
cert2_subj, @cert2_key, 10, cert2_exts, @cert, @cert_key)
|
||||
|
||||
ocsp_subj = OpenSSL::X509::Name.parse("/DC=org/DC=ruby-lang/CN=TestCAOCSP")
|
||||
@ocsp_key = OpenSSL::TestUtils::TEST_KEY_RSA2048
|
||||
|
@ -45,7 +42,7 @@ class OpenSSL::TestOCSP < OpenSSL::TestCase
|
|||
["extendedKeyUsage", "OCSPSigning", true],
|
||||
]
|
||||
@ocsp_cert = OpenSSL::TestUtils.issue_cert(
|
||||
ocsp_subj, @ocsp_key, 100, now, now+3600, ocsp_exts, @cert, @cert_key, "SHA256")
|
||||
ocsp_subj, @ocsp_key, 100, ocsp_exts, @cert, @cert_key)
|
||||
end
|
||||
|
||||
def test_new_certificate_id
|
||||
|
|
|
@ -259,18 +259,12 @@ module OpenSSL::TestPairM
|
|||
def test_write_nonblock_no_exceptions
|
||||
ssl_pair {|s1, s2|
|
||||
n = 0
|
||||
begin
|
||||
n += write_nonblock_no_ex s1, "a" * 100000
|
||||
n += write_nonblock_no_ex s1, "b" * 100000
|
||||
n += write_nonblock_no_ex s1, "c" * 100000
|
||||
n += write_nonblock_no_ex s1, "d" * 100000
|
||||
n += write_nonblock_no_ex s1, "e" * 100000
|
||||
n += write_nonblock_no_ex s1, "f" * 100000
|
||||
rescue OpenSSL::SSL::SSLError => e
|
||||
# on some platforms (maybe depend on OpenSSL version), writing to
|
||||
# SSLSocket after SSL_ERROR_WANT_WRITE causes this error.
|
||||
raise e if n == 0
|
||||
end
|
||||
n += write_nonblock_no_ex s1, "a" * 100000
|
||||
n += write_nonblock_no_ex s1, "b" * 100000
|
||||
n += write_nonblock_no_ex s1, "c" * 100000
|
||||
n += write_nonblock_no_ex s1, "d" * 100000
|
||||
n += write_nonblock_no_ex s1, "e" * 100000
|
||||
n += write_nonblock_no_ex s1, "f" * 100000
|
||||
s1.close
|
||||
assert_equal(n, s2.read.length)
|
||||
}
|
||||
|
|
|
@ -9,17 +9,13 @@ module OpenSSL
|
|||
|
||||
def setup
|
||||
ca = OpenSSL::X509::Name.parse("/DC=org/DC=ruby-lang/CN=CA")
|
||||
|
||||
now = Time.now
|
||||
ca_exts = [
|
||||
["basicConstraints","CA:TRUE",true],
|
||||
["keyUsage","keyCertSign, cRLSign",true],
|
||||
["subjectKeyIdentifier","hash",false],
|
||||
["authorityKeyIdentifier","keyid:always",false],
|
||||
]
|
||||
|
||||
@cacert = issue_cert(ca, TEST_KEY_RSA2048, 1, now, now+3600, ca_exts,
|
||||
nil, nil, OpenSSL::Digest::SHA1.new)
|
||||
@cacert = issue_cert(ca, TEST_KEY_RSA2048, 1, ca_exts, nil, nil)
|
||||
|
||||
inter_ca = OpenSSL::X509::Name.parse("/DC=org/DC=ruby-lang/CN=Intermediate CA")
|
||||
inter_ca_key = OpenSSL::PKey.read <<-_EOS_
|
||||
|
@ -39,17 +35,14 @@ FJx7d3f29gkzynCLJDkCQGQZlEZJC4vWmWJGRKJ24P6MyQn3VsPfErSKOg4lvyM3
|
|||
Li8JsX5yIiuVYaBg/6ha3tOg4TCa5K/3r3tVliRZ2Es=
|
||||
-----END RSA PRIVATE KEY-----
|
||||
_EOS_
|
||||
|
||||
@inter_cacert = issue_cert(inter_ca, inter_ca_key, 2, now, now+3600, ca_exts,
|
||||
@cacert, TEST_KEY_RSA2048, OpenSSL::Digest::SHA1.new)
|
||||
@inter_cacert = issue_cert(inter_ca, inter_ca_key, 2, ca_exts, @cacert, TEST_KEY_RSA2048)
|
||||
|
||||
exts = [
|
||||
["keyUsage","digitalSignature",true],
|
||||
["subjectKeyIdentifier","hash",false],
|
||||
]
|
||||
ee = OpenSSL::X509::Name.parse("/DC=org/DC=ruby-lang/CN=Ruby PKCS12 Test Certificate")
|
||||
@mycert = issue_cert(ee, TEST_KEY_RSA1024, 3, now, now+3600, exts,
|
||||
@inter_cacert, inter_ca_key, OpenSSL::Digest::SHA1.new)
|
||||
@mycert = issue_cert(ee, TEST_KEY_RSA1024, 3, exts, @inter_cacert, inter_ca_key)
|
||||
end
|
||||
|
||||
def test_create
|
||||
|
|
|
@ -11,24 +11,20 @@ class OpenSSL::TestPKCS7 < OpenSSL::TestCase
|
|||
ee1 = OpenSSL::X509::Name.parse("/DC=org/DC=ruby-lang/CN=EE1")
|
||||
ee2 = OpenSSL::X509::Name.parse("/DC=org/DC=ruby-lang/CN=EE2")
|
||||
|
||||
now = Time.now
|
||||
ca_exts = [
|
||||
["basicConstraints","CA:TRUE",true],
|
||||
["keyUsage","keyCertSign, cRLSign",true],
|
||||
["subjectKeyIdentifier","hash",false],
|
||||
["authorityKeyIdentifier","keyid:always",false],
|
||||
]
|
||||
@ca_cert = issue_cert(ca, @rsa2048, 1, now, now+3600, ca_exts,
|
||||
nil, nil, OpenSSL::Digest::SHA1.new)
|
||||
@ca_cert = issue_cert(ca, @rsa2048, 1, ca_exts, nil, nil)
|
||||
ee_exts = [
|
||||
["keyUsage","Non Repudiation, Digital Signature, Key Encipherment",true],
|
||||
["authorityKeyIdentifier","keyid:always",false],
|
||||
["extendedKeyUsage","clientAuth, emailProtection, codeSigning",false],
|
||||
]
|
||||
@ee1_cert = issue_cert(ee1, @rsa1024, 2, now, now+1800, ee_exts,
|
||||
@ca_cert, @rsa2048, OpenSSL::Digest::SHA1.new)
|
||||
@ee2_cert = issue_cert(ee2, @rsa1024, 3, now, now+1800, ee_exts,
|
||||
@ca_cert, @rsa2048, OpenSSL::Digest::SHA1.new)
|
||||
@ee1_cert = issue_cert(ee1, @rsa1024, 2, ee_exts, @ca_cert, @rsa2048)
|
||||
@ee2_cert = issue_cert(ee2, @rsa1024, 3, ee_exts, @ca_cert, @rsa2048)
|
||||
end
|
||||
|
||||
def issue_cert(*args)
|
||||
|
|
|
@ -36,6 +36,26 @@ class OpenSSL::TestPKeyDSA < OpenSSL::PKeyTestCase
|
|||
end
|
||||
end
|
||||
|
||||
def test_sign_verify
|
||||
data = "Sign me!"
|
||||
if defined?(OpenSSL::Digest::DSS1)
|
||||
signature = DSA512.sign(OpenSSL::Digest::DSS1.new, data)
|
||||
assert_equal true, DSA512.verify(OpenSSL::Digest::DSS1.new, signature, data)
|
||||
end
|
||||
|
||||
return if OpenSSL::OPENSSL_VERSION_NUMBER <= 0x010000000
|
||||
signature = DSA512.sign("SHA1", data)
|
||||
assert_equal true, DSA512.verify("SHA1", signature, data)
|
||||
|
||||
signature0 = (<<~'end;').unpack("m")[0]
|
||||
MCwCFH5h40plgU5Fh0Z4wvEEpz0eE9SnAhRPbkRB8ggsN/vsSEYMXvJwjGg/
|
||||
6g==
|
||||
end;
|
||||
assert_equal true, DSA512.verify("SHA256", signature0, data)
|
||||
signature1 = signature0.succ
|
||||
assert_equal false, DSA512.verify("SHA256", signature1, data)
|
||||
end
|
||||
|
||||
def test_sys_sign_verify
|
||||
key = OpenSSL::TestUtils::TEST_KEY_DSA256
|
||||
data = 'Sign me!'
|
||||
|
|
|
@ -73,6 +73,20 @@ class OpenSSL::TestEC < OpenSSL::PKeyTestCase
|
|||
assert_raise(OpenSSL::PKey::ECError) { key2.check_key }
|
||||
end
|
||||
|
||||
def test_sign_verify
|
||||
data = "Sign me!"
|
||||
signature = P256.sign("SHA1", data)
|
||||
assert_equal true, P256.verify("SHA1", signature, data)
|
||||
|
||||
signature0 = (<<~'end;').unpack("m")[0]
|
||||
MEQCIEOTY/hD7eI8a0qlzxkIt8LLZ8uwiaSfVbjX2dPAvN11AiAQdCYx56Fq
|
||||
QdBp1B4sxJoA8jvODMMklMyBKVmudboA6A==
|
||||
end;
|
||||
assert_equal true, P256.verify("SHA256", signature0, data)
|
||||
signature1 = signature0.succ
|
||||
assert_equal false, P256.verify("SHA256", signature1, data)
|
||||
end
|
||||
|
||||
def test_dsa_sign_verify
|
||||
data1 = "foo"
|
||||
data2 = "bar"
|
||||
|
@ -244,6 +258,10 @@ class OpenSSL::TestEC < OpenSSL::PKeyTestCase
|
|||
raise
|
||||
end
|
||||
|
||||
assert_equal 0x040603.to_bn, point.to_bn(:uncompressed)
|
||||
assert_equal 0x0306.to_bn, point.to_bn(:compressed)
|
||||
assert_equal 0x070603.to_bn, point.to_bn(:hybrid)
|
||||
|
||||
assert_equal 0x040603.to_bn, point.to_bn
|
||||
assert_equal true, point.on_curve?
|
||||
point.invert! # 8.5
|
||||
|
|
|
@ -70,6 +70,21 @@ class OpenSSL::TestPKeyRSA < OpenSSL::PKeyTestCase
|
|||
end
|
||||
end
|
||||
|
||||
def test_sign_verify
|
||||
data = "Sign me!"
|
||||
signature = RSA1024.sign("SHA1", data)
|
||||
assert_equal true, RSA1024.verify("SHA1", signature, data)
|
||||
|
||||
signature0 = (<<~'end;').unpack("m")[0]
|
||||
oLCgbprPvfhM4pjFQiDTFeWI9Sk+Og7Nh9TmIZ/xSxf2CGXQrptlwo7NQ28+
|
||||
WA6YQo8jPH4hSuyWIM4Gz4qRYiYRkl5TDMUYob94zm8Si1HxEiS9354tzvqS
|
||||
zS8MLW2BtNPuTubMxTItHGTnOzo9sUg0LAHVFt8kHG2NfKAw/gQ=
|
||||
end;
|
||||
assert_equal true, RSA1024.verify("SHA256", signature0, data)
|
||||
signature1 = signature0.succ
|
||||
assert_equal false, RSA1024.verify("SHA256", signature1, data)
|
||||
end
|
||||
|
||||
def test_digest_state_irrelevant_sign
|
||||
key = RSA1024
|
||||
digest1 = OpenSSL::Digest::SHA1.new
|
||||
|
@ -93,6 +108,13 @@ class OpenSSL::TestPKeyRSA < OpenSSL::PKeyTestCase
|
|||
assert(key.verify(digest2, sig, data))
|
||||
end
|
||||
|
||||
def test_verify_empty_rsa
|
||||
rsa = OpenSSL::PKey::RSA.new
|
||||
assert_raise(OpenSSL::PKey::PKeyError, "[Bug #12783]") {
|
||||
rsa.verify("SHA1", "a", "b")
|
||||
}
|
||||
end
|
||||
|
||||
def test_RSAPrivateKey
|
||||
asn1 = OpenSSL::ASN1::Sequence([
|
||||
OpenSSL::ASN1::Integer(0),
|
||||
|
|
|
@ -394,14 +394,12 @@ class OpenSSL::TestSSL < OpenSSL::SSLTestCase
|
|||
}
|
||||
}
|
||||
|
||||
now = Time.now
|
||||
exts = [
|
||||
["keyUsage","keyEncipherment,digitalSignature",true],
|
||||
["subjectAltName","DNS:localhost.localdomain",false],
|
||||
["subjectAltName","IP:127.0.0.1",false],
|
||||
]
|
||||
@svr_cert = issue_cert(@svr, @svr_key, 4, now, now+1800, exts,
|
||||
@ca_cert, @ca_key, OpenSSL::Digest::SHA1.new)
|
||||
@svr_cert = issue_cert(@svr, @svr_key, 4, exts, @ca_cert, @ca_key)
|
||||
start_server { |server, port|
|
||||
server_connect(port) { |ssl|
|
||||
assert(ssl.post_connection_check("localhost.localdomain"))
|
||||
|
@ -417,13 +415,11 @@ class OpenSSL::TestSSL < OpenSSL::SSLTestCase
|
|||
}
|
||||
}
|
||||
|
||||
now = Time.now
|
||||
exts = [
|
||||
["keyUsage","keyEncipherment,digitalSignature",true],
|
||||
["subjectAltName","DNS:*.localdomain",false],
|
||||
]
|
||||
@svr_cert = issue_cert(@svr, @svr_key, 5, now, now+1800, exts,
|
||||
@ca_cert, @ca_key, OpenSSL::Digest::SHA1.new)
|
||||
@svr_cert = issue_cert(@svr, @svr_key, 5, exts, @ca_cert, @ca_key)
|
||||
start_server { |server, port|
|
||||
server_connect(port) { |ssl|
|
||||
assert(ssl.post_connection_check("localhost.localdomain"))
|
||||
|
@ -656,7 +652,7 @@ class OpenSSL::TestSSL < OpenSSL::SSLTestCase
|
|||
ssl = OpenSSL::SSL::SSLSocket.new(sock, ctx)
|
||||
ssl.hostname = "foo.example.com"
|
||||
ssl.connect
|
||||
assert_match /^ADH-/, ssl.cipher[0], "the context returned by servername_cb is used"
|
||||
assert_match (/^ADH-/), ssl.cipher[0], "the context returned by servername_cb is used"
|
||||
assert_predicate ctx3, :frozen?
|
||||
ensure
|
||||
sock.close
|
||||
|
@ -667,7 +663,7 @@ class OpenSSL::TestSSL < OpenSSL::SSLTestCase
|
|||
ssl = OpenSSL::SSL::SSLSocket.new(sock, ctx)
|
||||
ssl.hostname = "bar.example.com"
|
||||
ssl.connect
|
||||
assert_not_match /^A(EC)?DH-/, ssl.cipher[0], "the original context is used"
|
||||
assert_not_match (/^A(EC)?DH-/), ssl.cipher[0], "the original context is used"
|
||||
ensure
|
||||
sock.close
|
||||
end
|
||||
|
@ -711,14 +707,12 @@ class OpenSSL::TestSSL < OpenSSL::SSLTestCase
|
|||
|
||||
def test_verify_hostname_on_connect
|
||||
ctx_proc = proc { |ctx|
|
||||
now = Time.now
|
||||
exts = [
|
||||
["keyUsage", "keyEncipherment,digitalSignature", true],
|
||||
["subjectAltName", "DNS:a.example.com,DNS:*.b.example.com," \
|
||||
"DNS:c*.example.com,DNS:d.*.example.com"],
|
||||
]
|
||||
ctx.cert = issue_cert(@svr, @svr_key, 4, now, now+1800, exts,
|
||||
@ca_cert, @ca_key, OpenSSL::Digest::SHA1.new)
|
||||
ctx.cert = issue_cert(@svr, @svr_key, 4, exts, @ca_cert, @ca_key)
|
||||
ctx.key = @svr_key
|
||||
}
|
||||
|
||||
|
@ -1252,6 +1246,18 @@ end
|
|||
sock2.close
|
||||
end
|
||||
|
||||
def test_freeze_calls_setup
|
||||
bug = "[ruby/openssl#85]"
|
||||
start_server(ignore_listener_error: true) { |server, port|
|
||||
ctx = OpenSSL::SSL::SSLContext.new
|
||||
ctx.verify_mode = OpenSSL::SSL::VERIFY_PEER
|
||||
ctx.freeze
|
||||
assert_raise(OpenSSL::SSL::SSLError, bug) {
|
||||
server_connect(port, ctx)
|
||||
}
|
||||
}
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def start_server_version(version, ctx_proc = nil,
|
||||
|
|
|
@ -11,7 +11,6 @@ class OpenSSL::TestX509Certificate < OpenSSL::TestCase
|
|||
@dsa512 = OpenSSL::TestUtils::TEST_KEY_DSA512
|
||||
@ca = OpenSSL::X509::Name.parse("/DC=org/DC=ruby-lang/CN=CA")
|
||||
@ee1 = OpenSSL::X509::Name.parse("/DC=org/DC=ruby-lang/CN=EE1")
|
||||
@ee2 = OpenSSL::X509::Name.parse("/DC=org/DC=ruby-lang/CN=EE2")
|
||||
end
|
||||
|
||||
def issue_cert(*args)
|
||||
|
@ -20,8 +19,7 @@ class OpenSSL::TestX509Certificate < OpenSSL::TestCase
|
|||
|
||||
def test_serial
|
||||
[1, 2**32, 2**100].each{|s|
|
||||
cert = issue_cert(@ca, @rsa2048, s, Time.now, Time.now+3600, [],
|
||||
nil, nil, OpenSSL::Digest::SHA1.new)
|
||||
cert = issue_cert(@ca, @rsa2048, s, [], nil, nil)
|
||||
assert_equal(s, cert.serial)
|
||||
cert = OpenSSL::X509::Certificate.new(cert.to_der)
|
||||
assert_equal(s, cert.serial)
|
||||
|
@ -41,8 +39,7 @@ class OpenSSL::TestX509Certificate < OpenSSL::TestCase
|
|||
[
|
||||
[@rsa1024, sha1], [@rsa2048, sha1], [@dsa256, dsa_digest], [@dsa512, dsa_digest]
|
||||
].each{|pk, digest|
|
||||
cert = issue_cert(@ca, pk, 1, Time.now, Time.now+3600, exts,
|
||||
nil, nil, digest)
|
||||
cert = issue_cert(@ca, pk, 1, exts, nil, nil, digest: digest)
|
||||
assert_equal(cert.extensions.sort_by(&:to_s)[2].value,
|
||||
OpenSSL::TestUtils.get_subject_key_id(cert))
|
||||
cert = OpenSSL::X509::Certificate.new(cert.to_der)
|
||||
|
@ -52,27 +49,27 @@ class OpenSSL::TestX509Certificate < OpenSSL::TestCase
|
|||
end
|
||||
|
||||
def test_validity
|
||||
now = Time.now until now && now.usec != 0
|
||||
cert = issue_cert(@ca, @rsa2048, 1, now, now+3600, [],
|
||||
nil, nil, OpenSSL::Digest::SHA1.new)
|
||||
assert_not_equal(now, cert.not_before)
|
||||
assert_not_equal(now+3600, cert.not_after)
|
||||
now = Time.at(Time.now.to_i + 0.9)
|
||||
cert = issue_cert(@ca, @rsa2048, 1, [], nil, nil,
|
||||
not_before: now, not_after: now+3600)
|
||||
assert_equal(Time.at(now.to_i), cert.not_before)
|
||||
assert_equal(Time.at(now.to_i+3600), cert.not_after)
|
||||
|
||||
now = Time.at(now.to_i)
|
||||
cert = issue_cert(@ca, @rsa2048, 1, now, now+3600, [],
|
||||
nil, nil, OpenSSL::Digest::SHA1.new)
|
||||
cert = issue_cert(@ca, @rsa2048, 1, [], nil, nil,
|
||||
not_before: now, not_after: now+3600)
|
||||
assert_equal(now.getutc, cert.not_before)
|
||||
assert_equal((now+3600).getutc, cert.not_after)
|
||||
|
||||
now = Time.at(0)
|
||||
cert = issue_cert(@ca, @rsa2048, 1, now, now, [],
|
||||
nil, nil, OpenSSL::Digest::SHA1.new)
|
||||
cert = issue_cert(@ca, @rsa2048, 1, [], nil, nil,
|
||||
not_before: now, not_after: now)
|
||||
assert_equal(now.getutc, cert.not_before)
|
||||
assert_equal(now.getutc, cert.not_after)
|
||||
|
||||
now = Time.at(0x7fffffff)
|
||||
cert = issue_cert(@ca, @rsa2048, 1, now, now, [],
|
||||
nil, nil, OpenSSL::Digest::SHA1.new)
|
||||
cert = issue_cert(@ca, @rsa2048, 1, [], nil, nil,
|
||||
not_before: now, not_after: now)
|
||||
assert_equal(now.getutc, cert.not_before)
|
||||
assert_equal(now.getutc, cert.not_after)
|
||||
end
|
||||
|
@ -84,8 +81,7 @@ class OpenSSL::TestX509Certificate < OpenSSL::TestCase
|
|||
["subjectKeyIdentifier","hash",false],
|
||||
["authorityKeyIdentifier","keyid:always",false],
|
||||
]
|
||||
ca_cert = issue_cert(@ca, @rsa2048, 1, Time.now, Time.now+3600, ca_exts,
|
||||
nil, nil, OpenSSL::Digest::SHA1.new)
|
||||
ca_cert = issue_cert(@ca, @rsa2048, 1, ca_exts, nil, nil)
|
||||
ca_cert.extensions.each_with_index{|ext, i|
|
||||
assert_equal(ca_exts[i].first, ext.oid)
|
||||
assert_equal(ca_exts[i].last, ext.critical?)
|
||||
|
@ -98,34 +94,16 @@ class OpenSSL::TestX509Certificate < OpenSSL::TestCase
|
|||
["extendedKeyUsage","clientAuth, emailProtection, codeSigning",false],
|
||||
["subjectAltName","email:ee1@ruby-lang.org",false],
|
||||
]
|
||||
ee1_cert = issue_cert(@ee1, @rsa1024, 2, Time.now, Time.now+1800, ee1_exts,
|
||||
ca_cert, @rsa2048, OpenSSL::Digest::SHA1.new)
|
||||
ee1_cert = issue_cert(@ee1, @rsa1024, 2, ee1_exts, ca_cert, @rsa2048)
|
||||
assert_equal(ca_cert.subject.to_der, ee1_cert.issuer.to_der)
|
||||
ee1_cert.extensions.each_with_index{|ext, i|
|
||||
assert_equal(ee1_exts[i].first, ext.oid)
|
||||
assert_equal(ee1_exts[i].last, ext.critical?)
|
||||
}
|
||||
|
||||
ee2_exts = [
|
||||
["keyUsage","Non Repudiation, Digital Signature, Key Encipherment",true],
|
||||
["subjectKeyIdentifier","hash",false],
|
||||
["authorityKeyIdentifier","issuer:always",false],
|
||||
["extendedKeyUsage","clientAuth, emailProtection, codeSigning",false],
|
||||
["subjectAltName","email:ee2@ruby-lang.org",false],
|
||||
]
|
||||
ee2_cert = issue_cert(@ee2, @rsa1024, 3, Time.now, Time.now+1800, ee2_exts,
|
||||
ca_cert, @rsa2048, OpenSSL::Digest::MD5.new)
|
||||
assert_equal(ca_cert.subject.to_der, ee2_cert.issuer.to_der)
|
||||
ee2_cert.extensions.each_with_index{|ext, i|
|
||||
assert_equal(ee2_exts[i].first, ext.oid)
|
||||
assert_equal(ee2_exts[i].last, ext.critical?)
|
||||
}
|
||||
|
||||
end
|
||||
|
||||
def test_sign_and_verify_rsa_sha1
|
||||
cert = issue_cert(@ca, @rsa2048, 1, Time.now, Time.now+3600, [],
|
||||
nil, nil, OpenSSL::Digest::SHA1.new)
|
||||
cert = issue_cert(@ca, @rsa2048, 1, [], nil, nil, digest: "sha1")
|
||||
assert_equal(false, cert.verify(@rsa1024))
|
||||
assert_equal(true, cert.verify(@rsa2048))
|
||||
assert_equal(false, certificate_error_returns_false { cert.verify(@dsa256) })
|
||||
|
@ -135,8 +113,7 @@ class OpenSSL::TestX509Certificate < OpenSSL::TestCase
|
|||
end
|
||||
|
||||
def test_sign_and_verify_rsa_md5
|
||||
cert = issue_cert(@ca, @rsa2048, 1, Time.now, Time.now+3600, [],
|
||||
nil, nil, OpenSSL::Digest::MD5.new)
|
||||
cert = issue_cert(@ca, @rsa2048, 1, [], nil, nil, digest: "md5")
|
||||
assert_equal(false, cert.verify(@rsa1024))
|
||||
assert_equal(true, cert.verify(@rsa2048))
|
||||
|
||||
|
@ -148,8 +125,7 @@ class OpenSSL::TestX509Certificate < OpenSSL::TestCase
|
|||
end
|
||||
|
||||
def test_sign_and_verify_dsa
|
||||
cert = issue_cert(@ca, @dsa512, 1, Time.now, Time.now+3600, [],
|
||||
nil, nil, OpenSSL::TestUtils::DSA_SIGNATURE_DIGEST.new)
|
||||
cert = issue_cert(@ca, @dsa512, 1, [], nil, nil)
|
||||
assert_equal(false, certificate_error_returns_false { cert.verify(@rsa1024) })
|
||||
assert_equal(false, certificate_error_returns_false { cert.verify(@rsa2048) })
|
||||
assert_equal(false, cert.verify(@dsa256))
|
||||
|
@ -159,8 +135,7 @@ class OpenSSL::TestX509Certificate < OpenSSL::TestCase
|
|||
end
|
||||
|
||||
def test_sign_and_verify_rsa_dss1
|
||||
cert = issue_cert(@ca, @rsa2048, 1, Time.now, Time.now+3600, [],
|
||||
nil, nil, OpenSSL::Digest::DSS1.new)
|
||||
cert = issue_cert(@ca, @rsa2048, 1, [], nil, nil, digest: OpenSSL::Digest::DSS1.new)
|
||||
assert_equal(false, cert.verify(@rsa1024))
|
||||
assert_equal(true, cert.verify(@rsa2048))
|
||||
assert_equal(false, certificate_error_returns_false { cert.verify(@dsa256) })
|
||||
|
@ -172,27 +147,19 @@ class OpenSSL::TestX509Certificate < OpenSSL::TestCase
|
|||
|
||||
def test_sign_and_verify_dsa_md5
|
||||
assert_raise(OpenSSL::X509::CertificateError){
|
||||
issue_cert(@ca, @dsa512, 1, Time.now, Time.now+3600, [],
|
||||
nil, nil, OpenSSL::Digest::MD5.new)
|
||||
issue_cert(@ca, @dsa512, 1, [], nil, nil, digest: "md5")
|
||||
}
|
||||
end
|
||||
|
||||
def test_dsig_algorithm_mismatch
|
||||
assert_raise(OpenSSL::X509::CertificateError) do
|
||||
issue_cert(@ca, @rsa2048, 1, Time.now, Time.now+3600, [],
|
||||
nil, nil, OpenSSL::Digest::DSS1.new)
|
||||
issue_cert(@ca, @rsa2048, 1, [], nil, nil, digest: OpenSSL::Digest::DSS1.new)
|
||||
end if OpenSSL::OPENSSL_VERSION_NUMBER < 0x10001000 # [ruby-core:42949]
|
||||
|
||||
assert_raise(OpenSSL::X509::CertificateError) do
|
||||
issue_cert(@ca, @dsa512, 1, Time.now, Time.now+3600, [],
|
||||
nil, nil, OpenSSL::Digest::MD5.new)
|
||||
end
|
||||
end
|
||||
|
||||
def test_dsa_with_sha2
|
||||
begin
|
||||
cert = issue_cert(@ca, @dsa256, 1, Time.now, Time.now+3600, [],
|
||||
nil, nil, OpenSSL::Digest::SHA256.new)
|
||||
cert = issue_cert(@ca, @dsa256, 1, [], nil, nil, digest: "sha256")
|
||||
assert_equal("dsa_with_SHA256", cert.signature_algorithm)
|
||||
rescue OpenSSL::X509::CertificateError
|
||||
# dsa_with_sha2 not supported. skip following test.
|
||||
|
@ -201,14 +168,12 @@ class OpenSSL::TestX509Certificate < OpenSSL::TestCase
|
|||
# TODO: need more tests for dsa + sha2
|
||||
|
||||
# SHA1 is allowed from OpenSSL 1.0.0 (0.9.8 requires DSS1)
|
||||
cert = issue_cert(@ca, @dsa256, 1, Time.now, Time.now+3600, [],
|
||||
nil, nil, OpenSSL::Digest::SHA1.new)
|
||||
cert = issue_cert(@ca, @dsa256, 1, [], nil, nil, digest: "sha1")
|
||||
assert_equal("dsaWithSHA1", cert.signature_algorithm)
|
||||
end if defined?(OpenSSL::Digest::SHA256)
|
||||
|
||||
def test_check_private_key
|
||||
cert = issue_cert(@ca, @rsa2048, 1, Time.now, Time.now+3600, [],
|
||||
nil, nil, OpenSSL::Digest::SHA1.new)
|
||||
cert = issue_cert(@ca, @rsa2048, 1, [], nil, nil)
|
||||
assert_equal(true, cert.check_private_key(@rsa2048))
|
||||
end
|
||||
|
||||
|
|
|
@ -25,8 +25,7 @@ class OpenSSL::TestX509CRL < OpenSSL::TestCase
|
|||
def test_basic
|
||||
now = Time.at(Time.now.to_i)
|
||||
|
||||
cert = issue_cert(@ca, @rsa2048, 1, now, now+3600, [],
|
||||
nil, nil, OpenSSL::Digest::SHA1.new)
|
||||
cert = issue_cert(@ca, @rsa2048, 1, [], nil, nil)
|
||||
crl = issue_crl([], 1, now, now+1600, [],
|
||||
cert, @rsa2048, OpenSSL::Digest::SHA1.new)
|
||||
assert_equal(1, crl.version)
|
||||
|
@ -63,8 +62,7 @@ class OpenSSL::TestX509CRL < OpenSSL::TestCase
|
|||
[4, now, 4],
|
||||
[5, now, 5],
|
||||
]
|
||||
cert = issue_cert(@ca, @rsa2048, 1, Time.now, Time.now+3600, [],
|
||||
nil, nil, OpenSSL::Digest::SHA1.new)
|
||||
cert = issue_cert(@ca, @rsa2048, 1, [], nil, nil)
|
||||
crl = issue_crl(revoke_info, 1, Time.now, Time.now+1600, [],
|
||||
cert, @rsa2048, OpenSSL::Digest::SHA1.new)
|
||||
revoked = crl.revoked
|
||||
|
@ -131,8 +129,7 @@ class OpenSSL::TestX509CRL < OpenSSL::TestCase
|
|||
["issuerAltName", "issuer:copy", false],
|
||||
]
|
||||
|
||||
cert = issue_cert(@ca, @rsa2048, 1, Time.now, Time.now+3600, cert_exts,
|
||||
nil, nil, OpenSSL::Digest::SHA1.new)
|
||||
cert = issue_cert(@ca, @rsa2048, 1, cert_exts, nil, nil)
|
||||
crl = issue_crl([], 1, Time.now, Time.now+1600, crl_exts,
|
||||
cert, @rsa2048, OpenSSL::Digest::SHA1.new)
|
||||
exts = crl.extensions
|
||||
|
@ -168,8 +165,7 @@ class OpenSSL::TestX509CRL < OpenSSL::TestCase
|
|||
end
|
||||
|
||||
def test_crlnumber
|
||||
cert = issue_cert(@ca, @rsa2048, 1, Time.now, Time.now+3600, [],
|
||||
nil, nil, OpenSSL::Digest::SHA1.new)
|
||||
cert = issue_cert(@ca, @rsa2048, 1, [], nil, nil)
|
||||
crl = issue_crl([], 1, Time.now, Time.now+1600, [],
|
||||
cert, @rsa2048, OpenSSL::Digest::SHA1.new)
|
||||
assert_match(1.to_s, crl.extensions[0].value)
|
||||
|
@ -187,8 +183,7 @@ class OpenSSL::TestX509CRL < OpenSSL::TestCase
|
|||
end
|
||||
|
||||
def test_sign_and_verify
|
||||
cert = issue_cert(@ca, @rsa2048, 1, Time.now, Time.now+3600, [],
|
||||
nil, nil, OpenSSL::Digest::SHA1.new)
|
||||
cert = issue_cert(@ca, @rsa2048, 1, [], nil, nil)
|
||||
crl = issue_crl([], 1, Time.now, Time.now+1600, [],
|
||||
cert, @rsa2048, OpenSSL::Digest::SHA1.new)
|
||||
assert_equal(false, crl.verify(@rsa1024))
|
||||
|
@ -198,8 +193,7 @@ class OpenSSL::TestX509CRL < OpenSSL::TestCase
|
|||
crl.version = 0
|
||||
assert_equal(false, crl.verify(@rsa2048))
|
||||
|
||||
cert = issue_cert(@ca, @dsa512, 1, Time.now, Time.now+3600, [],
|
||||
nil, nil, OpenSSL::TestUtils::DSA_SIGNATURE_DIGEST.new)
|
||||
cert = issue_cert(@ca, @dsa512, 1, [], nil, nil)
|
||||
crl = issue_crl([], 1, Time.now, Time.now+1600, [],
|
||||
cert, @dsa512, OpenSSL::TestUtils::DSA_SIGNATURE_DIGEST.new)
|
||||
assert_equal(false, crl_error_returns_false { crl.verify(@rsa1024) })
|
||||
|
|
|
@ -345,13 +345,13 @@ class OpenSSL::TestX509Name < OpenSSL::TestCase
|
|||
def test_hash
|
||||
dn = "/DC=org/DC=ruby-lang/CN=www.ruby-lang.org"
|
||||
name = OpenSSL::X509::Name.parse(dn)
|
||||
d = Digest::MD5.digest(name.to_der)
|
||||
d = OpenSSL::Digest::MD5.digest(name.to_der)
|
||||
expected = (d[0].ord & 0xff) | (d[1].ord & 0xff) << 8 | (d[2].ord & 0xff) << 16 | (d[3].ord & 0xff) << 24
|
||||
assert_equal(expected, name_hash(name))
|
||||
#
|
||||
dn = "/DC=org/DC=ruby-lang/CN=baz.ruby-lang.org"
|
||||
name = OpenSSL::X509::Name.parse(dn)
|
||||
d = Digest::MD5.digest(name.to_der)
|
||||
d = OpenSSL::Digest::MD5.digest(name.to_der)
|
||||
expected = (d[0].ord & 0xff) | (d[1].ord & 0xff) << 8 | (d[2].ord & 0xff) << 16 | (d[3].ord & 0xff) << 24
|
||||
assert_equal(expected, name_hash(name))
|
||||
end
|
||||
|
|
|
@ -34,7 +34,9 @@ class OpenSSL::TestX509Store < OpenSSL::TestCase
|
|||
end
|
||||
|
||||
def test_verify
|
||||
now = Time.at(Time.now.to_i)
|
||||
# OpenSSL uses time(2) while Time.now uses clock_gettime(CLOCK_REALTIME),
|
||||
# and there may be difference.
|
||||
now = Time.now - 3
|
||||
ca_exts = [
|
||||
["basicConstraints","CA:TRUE",true],
|
||||
["keyUsage","cRLSign,keyCertSign",true],
|
||||
|
@ -42,18 +44,15 @@ class OpenSSL::TestX509Store < OpenSSL::TestCase
|
|||
ee_exts = [
|
||||
["keyUsage","keyEncipherment,digitalSignature",true],
|
||||
]
|
||||
ca1_cert = issue_cert(@ca1, @rsa2048, 1, now, now+3600, ca_exts,
|
||||
nil, nil, OpenSSL::Digest::SHA1.new)
|
||||
ca2_cert = issue_cert(@ca2, @rsa1024, 2, now, now+1800, ca_exts,
|
||||
ca1_cert, @rsa2048, OpenSSL::Digest::SHA1.new)
|
||||
ee1_cert = issue_cert(@ee1, @dsa256, 10, now, now+1800, ee_exts,
|
||||
ca2_cert, @rsa1024, OpenSSL::Digest::SHA1.new)
|
||||
ee2_cert = issue_cert(@ee2, @dsa512, 20, now, now+1800, ee_exts,
|
||||
ca2_cert, @rsa1024, OpenSSL::Digest::SHA1.new)
|
||||
ee3_cert = issue_cert(@ee2, @dsa512, 30, now-100, now-1, ee_exts,
|
||||
ca2_cert, @rsa1024, OpenSSL::Digest::SHA1.new)
|
||||
ee4_cert = issue_cert(@ee2, @dsa512, 40, now+1000, now+2000, ee_exts,
|
||||
ca2_cert, @rsa1024, OpenSSL::Digest::SHA1.new)
|
||||
ca1_cert = issue_cert(@ca1, @rsa2048, 1, ca_exts, nil, nil)
|
||||
ca2_cert = issue_cert(@ca2, @rsa1024, 2, ca_exts, ca1_cert, @rsa2048,
|
||||
not_after: now+1800)
|
||||
ee1_cert = issue_cert(@ee1, @dsa256, 10, ee_exts, ca2_cert, @rsa1024)
|
||||
ee2_cert = issue_cert(@ee2, @dsa512, 20, ee_exts, ca2_cert, @rsa1024)
|
||||
ee3_cert = issue_cert(@ee2, @dsa512, 30, ee_exts, ca2_cert, @rsa1024,
|
||||
not_before: now-100, not_after: now-1)
|
||||
ee4_cert = issue_cert(@ee2, @dsa512, 40, ee_exts, ca2_cert, @rsa1024,
|
||||
not_before: now+1000, not_after: now+2000,)
|
||||
|
||||
revoke_info = []
|
||||
crl1 = issue_crl(revoke_info, 1, now, now+1800, [],
|
||||
|
@ -195,8 +194,7 @@ class OpenSSL::TestX509Store < OpenSSL::TestCase
|
|||
|
||||
def test_set_errors
|
||||
now = Time.now
|
||||
ca1_cert = issue_cert(@ca1, @rsa2048, 1, now, now+3600, [],
|
||||
nil, nil, OpenSSL::Digest::SHA1.new)
|
||||
ca1_cert = issue_cert(@ca1, @rsa2048, 1, [], nil, nil)
|
||||
store = OpenSSL::X509::Store.new
|
||||
store.add_cert(ca1_cert)
|
||||
assert_raise(OpenSSL::X509::StoreError){
|
||||
|
|
|
@ -10,7 +10,6 @@ rescue LoadError
|
|||
end
|
||||
|
||||
require "test/unit"
|
||||
require "digest/md5"
|
||||
require 'tempfile'
|
||||
require "rbconfig"
|
||||
require "socket"
|
||||
|
@ -131,8 +130,8 @@ AQjjxMXhwULlmuR/K+WwlaZPiLIBYalLAZQ7ZbOPeVkJ8ePao0eLAgEC
|
|||
|
||||
module_function
|
||||
|
||||
def issue_cert(dn, key, serial, not_before, not_after, extensions,
|
||||
issuer, issuer_key, digest)
|
||||
def issue_cert(dn, key, serial, extensions, issuer, issuer_key,
|
||||
not_before: nil, not_after: nil, digest: nil)
|
||||
cert = OpenSSL::X509::Certificate.new
|
||||
issuer = cert unless issuer
|
||||
issuer_key = key unless issuer_key
|
||||
|
@ -141,14 +140,16 @@ AQjjxMXhwULlmuR/K+WwlaZPiLIBYalLAZQ7ZbOPeVkJ8ePao0eLAgEC
|
|||
cert.subject = dn
|
||||
cert.issuer = issuer.subject
|
||||
cert.public_key = key.public_key
|
||||
cert.not_before = not_before
|
||||
cert.not_after = not_after
|
||||
now = Time.now
|
||||
cert.not_before = not_before || now - 3600
|
||||
cert.not_after = not_after || now + 3600
|
||||
ef = OpenSSL::X509::ExtensionFactory.new
|
||||
ef.subject_certificate = cert
|
||||
ef.issuer_certificate = issuer
|
||||
extensions.each{|oid, value, critical|
|
||||
cert.add_extension(ef.create_extension(oid, value, critical))
|
||||
}
|
||||
digest ||= OpenSSL::PKey::DSA === issuer_key ? DSA_SIGNATURE_DIGEST.new : "sha256"
|
||||
cert.sign(issuer_key, digest)
|
||||
cert
|
||||
end
|
||||
|
@ -217,7 +218,6 @@ AQjjxMXhwULlmuR/K+WwlaZPiLIBYalLAZQ7ZbOPeVkJ8ePao0eLAgEC
|
|||
@ca = OpenSSL::X509::Name.parse("/DC=org/DC=ruby-lang/CN=CA")
|
||||
@svr = OpenSSL::X509::Name.parse("/DC=org/DC=ruby-lang/CN=localhost")
|
||||
@cli = OpenSSL::X509::Name.parse("/DC=org/DC=ruby-lang/CN=localhost")
|
||||
now = Time.at(Time.now.to_i)
|
||||
ca_exts = [
|
||||
["basicConstraints","CA:TRUE",true],
|
||||
["keyUsage","cRLSign,keyCertSign",true],
|
||||
|
@ -225,9 +225,9 @@ AQjjxMXhwULlmuR/K+WwlaZPiLIBYalLAZQ7ZbOPeVkJ8ePao0eLAgEC
|
|||
ee_exts = [
|
||||
["keyUsage","keyEncipherment,digitalSignature",true],
|
||||
]
|
||||
@ca_cert = issue_cert(@ca, @ca_key, 1, now, now+3600, ca_exts, nil, nil, OpenSSL::Digest::SHA1.new)
|
||||
@svr_cert = issue_cert(@svr, @svr_key, 2, now, now+1800, ee_exts, @ca_cert, @ca_key, OpenSSL::Digest::SHA1.new)
|
||||
@cli_cert = issue_cert(@cli, @cli_key, 3, now, now+1800, ee_exts, @ca_cert, @ca_key, OpenSSL::Digest::SHA1.new)
|
||||
@ca_cert = issue_cert(@ca, @ca_key, 1, ca_exts, nil, nil)
|
||||
@svr_cert = issue_cert(@svr, @svr_key, 2, ee_exts, @ca_cert, @ca_key)
|
||||
@cli_cert = issue_cert(@cli, @cli_key, 3, ee_exts, @ca_cert, @ca_key)
|
||||
@server = nil
|
||||
end
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче