aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.travis.yml3
-rw-r--r--CONTRIBUTING.md2
-rw-r--r--History.md5
-rw-r--r--README.md12
-rw-r--r--Rakefile25
-rw-r--r--appveyor.yml16
-rw-r--r--ext/openssl/extconf.rb6
-rw-r--r--ext/openssl/ossl.c115
-rw-r--r--ext/openssl/ossl.h42
-rw-r--r--ext/openssl/ossl_asn1.c9
-rw-r--r--ext/openssl/ossl_bio.c3
-rw-r--r--ext/openssl/ossl_cipher.c77
-rw-r--r--ext/openssl/ossl_ns_spki.c7
-rw-r--r--ext/openssl/ossl_pkcs7.c2
-rw-r--r--ext/openssl/ossl_pkey.c67
-rw-r--r--ext/openssl/ossl_pkey.h1
-rw-r--r--ext/openssl/ossl_pkey_dsa.c4
-rw-r--r--ext/openssl/ossl_pkey_ec.c64
-rw-r--r--ext/openssl/ossl_pkey_rsa.c10
-rw-r--r--ext/openssl/ossl_ssl.c16
-rw-r--r--ext/openssl/ossl_ssl_session.c55
-rw-r--r--ext/openssl/ossl_x509.h9
-rw-r--r--ext/openssl/ossl_x509cert.c2
-rw-r--r--ext/openssl/ossl_x509crl.c29
-rw-r--r--ext/openssl/ossl_x509req.c22
-rw-r--r--ext/openssl/ossl_x509store.c108
-rw-r--r--ext/openssl/ruby_missing.h9
-rw-r--r--lib/openssl/buffering.rb8
-rw-r--r--openssl.gemspec6
-rw-r--r--test/test_cipher.rb482
-rw-r--r--test/test_digest.rb36
-rw-r--r--test/test_hmac.rb44
-rw-r--r--test/test_pair.rb18
-rw-r--r--test/test_pkey.rb56
-rw-r--r--test/test_pkey_dsa.rb20
-rw-r--r--test/test_pkey_ec.rb18
-rw-r--r--test/test_pkey_rsa.rb22
-rw-r--r--test/test_x509name.rb4
-rw-r--r--test/utils.rb1
-rw-r--r--tool/ruby-openssl-docker/Dockerfile38
-rw-r--r--tool/ruby-openssl-docker/README.md5
-rwxr-xr-xtool/ruby-openssl-docker/init.sh11
42 files changed, 681 insertions, 808 deletions
diff --git a/.travis.yml b/.travis.yml
index 30d967c0..c770d989 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -21,8 +21,7 @@ matrix:
- env: RUBY_VERSION=ruby-2.3 OPENSSL_VERSION=openssl-1.0.1 OSSL_MDEBUG=1
- env: RUBY_VERSION=ruby-2.3 OPENSSL_VERSION=openssl-1.0.2 OSSL_MDEBUG=1
- env: RUBY_VERSION=ruby-2.3 OPENSSL_VERSION=openssl-1.1.0 OSSL_MDEBUG=1
- - env: RUBY_VERSION=ruby-2.3 OPENSSL_VERSION=libressl-2.1
- - env: RUBY_VERSION=ruby-2.3 OPENSSL_VERSION=libressl-2.2
- env: RUBY_VERSION=ruby-2.3 OPENSSL_VERSION=libressl-2.3
- env: RUBY_VERSION=ruby-2.3 OPENSSL_VERSION=libressl-2.4
+ - env: RUBY_VERSION=ruby-2.3 OPENSSL_VERSION=libressl-2.5
allow_failures:
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 523c555e..6e6e2a54 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -44,7 +44,7 @@ Test cases are located under the
You can run it with the following three commands:
```
-$ gem install rake-compiler test-unit
+$ rake install_dependencies # installs rake-compiler, test-unit, ...
$ rake compile
$ rake test
```
diff --git a/History.md b/History.md
index 802275ef..029426fb 100644
--- a/History.md
+++ b/History.md
@@ -17,7 +17,7 @@ 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.1, 2.2, 2.3, 2.4
+* LibreSSL 2.3, 2.4, 2.5
* Ruby 2.3, 2.4
Notable changes
@@ -70,6 +70,9 @@ Notable changes
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
diff --git a/README.md b/README.md
index d01cf826..21d0f528 100644
--- a/README.md
+++ b/README.md
@@ -1,6 +1,7 @@
-# OpenSSL
+# OpenSSL for Ruby
[![Build Status](https://travis-ci.org/ruby/openssl.svg?branch=master)](https://travis-ci.org/ruby/openssl)
+[![Build status](https://ci.appveyor.com/api/projects/status/b8djtmwo7l26f88y/branch/master?svg=true)](https://ci.appveyor.com/project/ruby/openssl/branch/master)
OpenSSL provides SSL, TLS and general purpose cryptography. It wraps the
OpenSSL library.
@@ -48,14 +49,9 @@ gem "openssl"
require "openssl"
```
-See the documentation on OpenSSL for more usage,
-and the official [OpenSSL library](http://www.openssl.org/).
+## Documentation
-## Getting Started
-
-1. `$ gem install rake-compiler test-unit`
-2. `$ rake compile`
-3. `$ rake test`
+See https://ruby.github.io/openssl/.
## Contributing
diff --git a/Rakefile b/Rakefile
index f3e7e3fa..91502607 100644
--- a/Rakefile
+++ b/Rakefile
@@ -1,11 +1,14 @@
-gem 'rake-compiler'
-
require 'rake'
-require 'rake/extensiontask'
require 'rake/testtask'
require 'rdoc/task'
-Rake::ExtensionTask.new('openssl')
+begin
+ require 'rake/extensiontask'
+ Rake::ExtensionTask.new('openssl')
+rescue LoadError
+ warn "rake-compiler not installed. Run 'rake install_dependencies' to " \
+ "install testing dependency gems."
+end
Rake::TestTask.new do |t|
t.libs << 'test'
@@ -22,6 +25,20 @@ task :debug do
ruby "-I./lib -ropenssl -ve'puts OpenSSL::OPENSSL_VERSION, OpenSSL::OPENSSL_LIBRARY_VERSION'"
end
+task :install_dependencies do
+ if ENV["USE_HTTP_RUBYGEMS_ORG"] == "1"
+ Gem.sources.replace([Gem::Source.new("http://rubygems.org")])
+ end
+
+ Gem.configuration.verbose = false
+ gemspec = eval(File.read("openssl.gemspec"))
+ gemspec.development_dependencies.each do |dep|
+ print "Installing #{dep.name} (#{dep.requirement}) ... "
+ gem = Gem.install(dep.name, dep.requirement, force: true)
+ puts "#{gem[0].version}"
+ end
+end
+
namespace :sync do
task :from_ruby do
sh "./tool/sync-with-trunk"
diff --git a/appveyor.yml b/appveyor.yml
new file mode 100644
index 00000000..c3e9c303
--- /dev/null
+++ b/appveyor.yml
@@ -0,0 +1,16 @@
+---
+clone_depth: 10
+install:
+ - SET PATH=C:\Ruby%ruby_version%\bin;%PATH%
+ - appveyor DownloadFile http://dl.bintray.com/oneclick/OpenKnapsack/x64/openssl-1.0.1m-x64-windows.tar.lzma
+ - 7z e openssl-1.0.1m-x64-windows.tar.lzma
+ - 7z x -y -oC:\Ruby%ruby_version% openssl-1.0.1m-x64-windows.tar
+ - ruby -S rake install_dependencies
+build_script:
+ - rake -rdevkit compile -- --with-openssl-dir=C:\Ruby%ruby_version%
+test_script:
+ - rake test
+deploy: off
+environment:
+ matrix:
+ - ruby_version: "23-x64"
diff --git a/ext/openssl/extconf.rb b/ext/openssl/extconf.rb
index 20c67c6b..a812e59d 100644
--- a/ext/openssl/extconf.rb
+++ b/ext/openssl/extconf.rb
@@ -33,14 +33,8 @@ end
Logging::message "=== Checking for system dependent stuff... ===\n"
have_library("nsl", "t_open")
have_library("socket", "socket")
-have_header("assert.h")
Logging::message "=== Checking for required stuff... ===\n"
-if $mingw
- have_library("wsock32")
- have_library("gdi32")
-end
-
result = pkg_config("openssl") && have_header("openssl/ssl.h")
unless result
result = have_header("openssl/ssl.h")
diff --git a/ext/openssl/ossl.c b/ext/openssl/ossl.c
index a9000f25..8269599f 100644
--- a/ext/openssl/ossl.c
+++ b/ext/openssl/ossl.c
@@ -149,7 +149,7 @@ ossl_pem_passwd_value(VALUE pass)
/* PEM_BUFSIZE is currently used as the second argument of pem_password_cb,
* that is +max_len+ of ossl_pem_passwd_cb() */
if (RSTRING_LEN(pass) > PEM_BUFSIZE)
- ossl_raise(eOSSLError, "password must be shorter than %d bytes", PEM_BUFSIZE);
+ ossl_raise(eOSSLError, "password must not be longer than %d bytes", PEM_BUFSIZE);
return pass;
}
@@ -168,7 +168,8 @@ ossl_pem_passwd_cb0(VALUE flag)
int
ossl_pem_passwd_cb(char *buf, int max_len, int flag, void *pwd_)
{
- int len, status;
+ long len;
+ int status;
VALUE rflag, pass = (VALUE)pwd_;
if (RTEST(pass)) {
@@ -176,7 +177,7 @@ ossl_pem_passwd_cb(char *buf, int max_len, int flag, void *pwd_)
* work because it does not allow NUL characters and truncates to 1024
* bytes silently if the input is over 1024 bytes */
if (RB_TYPE_P(pass, T_STRING)) {
- len = RSTRING_LENINT(pass);
+ len = RSTRING_LEN(pass);
if (len >= OSSL_MIN_PWD_LEN && len <= max_len) {
memcpy(buf, RSTRING_PTR(pass), len);
return len;
@@ -203,78 +204,19 @@ ossl_pem_passwd_cb(char *buf, int max_len, int flag, void *pwd_)
rb_set_errinfo(Qnil);
return -1;
}
- len = RSTRING_LENINT(pass);
+ len = RSTRING_LEN(pass);
if (len < OSSL_MIN_PWD_LEN) {
rb_warning("password must be at least %d bytes", OSSL_MIN_PWD_LEN);
continue;
}
if (len > max_len) {
- rb_warning("password must be shorter than %d bytes", max_len);
+ rb_warning("password must not be longer than %d bytes", max_len);
continue;
}
memcpy(buf, RSTRING_PTR(pass), len);
break;
}
- return len;
-}
-
-/*
- * Verify callback
- */
-int ossl_store_ctx_ex_verify_cb_idx;
-int ossl_store_ex_verify_cb_idx;
-
-struct ossl_verify_cb_args {
- VALUE proc;
- VALUE preverify_ok;
- VALUE store_ctx;
-};
-
-static VALUE
-ossl_call_verify_cb_proc(struct ossl_verify_cb_args *args)
-{
- return rb_funcall(args->proc, rb_intern("call"), 2,
- args->preverify_ok, args->store_ctx);
-}
-
-int
-ossl_verify_cb_call(VALUE proc, int ok, X509_STORE_CTX *ctx)
-{
- VALUE rctx, ret;
- struct ossl_verify_cb_args args;
- int state;
-
- if (NIL_P(proc))
- return ok;
-
- ret = Qfalse;
- rctx = rb_protect((VALUE(*)(VALUE))ossl_x509stctx_new, (VALUE)ctx, &state);
- if (state) {
- rb_set_errinfo(Qnil);
- rb_warn("StoreContext initialization failure");
- }
- else {
- args.proc = proc;
- args.preverify_ok = ok ? Qtrue : Qfalse;
- args.store_ctx = rctx;
- ret = rb_protect((VALUE(*)(VALUE))ossl_call_verify_cb_proc, (VALUE)&args, &state);
- if (state) {
- rb_set_errinfo(Qnil);
- rb_warn("exception in verify_callback is ignored");
- }
- ossl_x509stctx_clear_ptr(rctx);
- }
- if (ret == Qtrue) {
- X509_STORE_CTX_set_error(ctx, X509_V_OK);
- ok = 1;
- }
- else {
- if (X509_STORE_CTX_get_error(ctx) == X509_V_OK)
- X509_STORE_CTX_set_error(ctx, X509_V_ERR_CERT_REJECTED);
- ok = 0;
- }
-
- return ok;
+ return (int)len;
}
/*
@@ -355,27 +297,32 @@ ossl_raise(VALUE exc, const char *fmt, ...)
rb_exc_raise(err);
}
-VALUE
-ossl_exc_new(VALUE exc, const char *fmt, ...)
-{
- va_list args;
- VALUE err;
- va_start(args, fmt);
- err = ossl_make_error(exc, fmt, args);
- va_end(args);
- return err;
-}
-
void
ossl_clear_error(void)
{
if (dOSSL == Qtrue) {
- long e;
- while ((e = ERR_get_error())) {
- rb_warn("error on stack: %s", ERR_error_string(e, NULL));
+ unsigned long e;
+ const char *file, *data, *errstr;
+ int line, flags;
+
+ while ((e = ERR_get_error_line_data(&file, &line, &data, &flags))) {
+ errstr = ERR_error_string(e, NULL);
+ if (!errstr)
+ errstr = "(null)";
+
+ if (flags & ERR_TXT_STRING) {
+ if (!data)
+ data = "(null)";
+ rb_warn("error on stack: %s (%s)", errstr, data);
+ }
+ else {
+ rb_warn("error on stack: %s", errstr);
+ }
}
}
- ERR_clear_error();
+ else {
+ ERR_clear_error();
+ }
}
/*
@@ -1152,14 +1099,6 @@ Init_openssl(void)
rb_define_module_function(mOSSL, "errors", ossl_get_errors, 0);
/*
- * Verify callback Proc index for ext-data
- */
- if ((ossl_store_ctx_ex_verify_cb_idx = X509_STORE_CTX_get_ex_new_index(0, (void *)"ossl_store_ctx_ex_verify_cb_idx", 0, 0, 0)) < 0)
- ossl_raise(eOSSLError, "X509_STORE_CTX_get_ex_new_index");
- if ((ossl_store_ex_verify_cb_idx = X509_STORE_get_ex_new_index(0, (void *)"ossl_store_ex_verify_cb_idx", 0, 0, 0)) < 0)
- ossl_raise(eOSSLError, "X509_STORE_get_ex_new_index");
-
- /*
* Get ID of to_der
*/
ossl_s_to_der = rb_intern("to_der");
diff --git a/ext/openssl/ossl.h b/ext/openssl/ossl.h
index 864d0683..78eddd09 100644
--- a/ext/openssl/ossl.h
+++ b/ext/openssl/ossl.h
@@ -12,37 +12,12 @@
#include RUBY_EXTCONF_H
-#if 0
- mOSSL = rb_define_module("OpenSSL");
- mX509 = rb_define_module_under(mOSSL, "X509");
-#endif
-
-/*
-* OpenSSL has defined RFILE and Ruby has defined RFILE - so undef it!
-*/
-#if defined(RFILE) /*&& !defined(OSSL_DEBUG)*/
-# undef RFILE
-#endif
+#include <assert.h>
+#include <errno.h>
#include <ruby.h>
#include <ruby/io.h>
#include <ruby/thread.h>
-
#include <openssl/opensslv.h>
-
-#ifdef HAVE_ASSERT_H
-# include <assert.h>
-#else
-# define assert(condition)
-#endif
-
-#if defined(_WIN32) && !defined(LIBRESSL_VERSION_NUMBER)
-# include <openssl/e_os2.h>
-# if !defined(OPENSSL_SYS_WIN32)
-# define OPENSSL_SYS_WIN32 1
-# endif
-# include <winsock2.h>
-#endif
-#include <errno.h>
#include <openssl/err.h>
#include <openssl/asn1.h>
#include <openssl/x509v3.h>
@@ -53,9 +28,7 @@
#include <openssl/rand.h>
#include <openssl/conf.h>
#include <openssl/conf_api.h>
-#if !defined(_WIN32)
-# include <openssl/crypto.h>
-#endif
+#include <openssl/crypto.h>
#if !defined(OPENSSL_NO_ENGINE)
# include <openssl/engine.h>
#endif
@@ -144,19 +117,10 @@ int ossl_pem_passwd_cb(char *, int, int, void *);
*/
#define OSSL_ErrMsg() ERR_reason_error_string(ERR_get_error())
NORETURN(void ossl_raise(VALUE, const char *, ...));
-VALUE ossl_exc_new(VALUE, const char *, ...);
/* Clear OpenSSL error queue. If dOSSL is set, rb_warn() them. */
void ossl_clear_error(void);
/*
- * Verify callback
- */
-extern int ossl_store_ctx_ex_verify_cb_idx;
-extern int ossl_store_ex_verify_cb_idx;
-
-int ossl_verify_cb_call(VALUE, int, X509_STORE_CTX *);
-
-/*
* String to DER String
*/
extern ID ossl_s_to_der;
diff --git a/ext/openssl/ossl_asn1.c b/ext/openssl/ossl_asn1.c
index 90d35c6d..9d759c1e 100644
--- a/ext/openssl/ossl_asn1.c
+++ b/ext/openssl/ossl_asn1.c
@@ -9,15 +9,6 @@
*/
#include "ossl.h"
-#if defined(HAVE_SYS_TIME_H)
-# include <sys/time.h>
-#elif !defined(NT) && !defined(_WIN32)
-struct timeval {
- long tv_sec; /* seconds */
- long tv_usec; /* and microseconds */
-};
-#endif
-
static VALUE join_der(VALUE enumerable);
static VALUE ossl_asn1_decode0(unsigned char **pp, long length, long *offset,
int depth, int yield, long *num_read);
diff --git a/ext/openssl/ossl_bio.c b/ext/openssl/ossl_bio.c
index feaf2296..1609b097 100644
--- a/ext/openssl/ossl_bio.c
+++ b/ext/openssl/ossl_bio.c
@@ -8,9 +8,6 @@
* (See the file 'LICENCE'.)
*/
#include "ossl.h"
-#ifdef HAVE_UNISTD_H
-#include <unistd.h>
-#endif
BIO *
ossl_obj2bio(VALUE obj)
diff --git a/ext/openssl/ossl_cipher.c b/ext/openssl/ossl_cipher.c
index 57bc3cfa..73b667b2 100644
--- a/ext/openssl/ossl_cipher.c
+++ b/ext/openssl/ossl_cipher.c
@@ -36,7 +36,7 @@
*/
VALUE cCipher;
VALUE eCipherError;
-static ID id_auth_tag_len;
+static ID id_auth_tag_len, id_key_set;
static VALUE ossl_cipher_alloc(VALUE klass);
static void ossl_cipher_free(void *ptr);
@@ -118,7 +118,6 @@ ossl_cipher_initialize(VALUE self, VALUE str)
EVP_CIPHER_CTX *ctx;
const EVP_CIPHER *cipher;
char *name;
- unsigned char dummy_key[EVP_MAX_KEY_LENGTH] = { 0 };
name = StringValueCStr(str);
GetCipherInit(self, ctx);
@@ -129,16 +128,7 @@ ossl_cipher_initialize(VALUE self, VALUE str)
if (!(cipher = EVP_get_cipherbyname(name))) {
ossl_raise(rb_eRuntimeError, "unsupported cipher algorithm (%"PRIsVALUE")", str);
}
- /*
- * EVP_CipherInit_ex() allows to specify NULL to key and IV, however some
- * ciphers don't handle well (OpenSSL's bug). [Bug #2768]
- *
- * The EVP which has EVP_CIPH_RAND_KEY flag (such as DES3) allows
- * uninitialized key, but other EVPs (such as AES) does not allow it.
- * Calling EVP_CipherUpdate() without initializing key causes SEGV so we
- * set the data filled with "\0" as the key by default.
- */
- if (EVP_CipherInit_ex(ctx, cipher, NULL, dummy_key, NULL, -1) != 1)
+ if (EVP_CipherInit_ex(ctx, cipher, NULL, NULL, NULL, -1) != 1)
ossl_raise(eCipherError, NULL);
return self;
@@ -251,6 +241,9 @@ ossl_cipher_init(int argc, VALUE *argv, VALUE self, int mode)
ossl_raise(eCipherError, NULL);
}
+ if (p_key)
+ rb_ivar_set(self, id_key_set, Qtrue);
+
return self;
}
@@ -337,6 +330,8 @@ ossl_cipher_pkcs5_keyivgen(int argc, VALUE *argv, VALUE self)
OPENSSL_cleanse(key, sizeof key);
OPENSSL_cleanse(iv, sizeof iv);
+ rb_ivar_set(self, id_key_set, Qtrue);
+
return Qnil;
}
@@ -387,6 +382,9 @@ ossl_cipher_update(int argc, VALUE *argv, VALUE self)
rb_scan_args(argc, argv, "11", &data, &str);
+ if (!RTEST(rb_attr_get(self, id_key_set)))
+ ossl_raise(eCipherError, "key not set");
+
StringValue(data);
in = (unsigned char *)RSTRING_PTR(data);
if ((in_len = RSTRING_LEN(data)) == 0)
@@ -488,6 +486,8 @@ ossl_cipher_set_key(VALUE self, VALUE key)
if (EVP_CipherInit_ex(ctx, NULL, NULL, (unsigned char *)RSTRING_PTR(key), NULL, -1) != 1)
ossl_raise(eCipherError, NULL);
+ rb_ivar_set(self, id_key_set, Qtrue);
+
return key;
}
@@ -502,9 +502,6 @@ ossl_cipher_set_key(VALUE self, VALUE key)
* Cipher#random_iv to create a secure random IV.
*
* Only call this method after calling Cipher#encrypt or Cipher#decrypt.
- *
- * If not explicitly set, the OpenSSL default of an all-zeroes ("\\0") IV is
- * used.
*/
static VALUE
ossl_cipher_set_iv(VALUE self, VALUE iv)
@@ -530,6 +527,27 @@ ossl_cipher_set_iv(VALUE self, VALUE iv)
return iv;
}
+/*
+ * call-seq:
+ * cipher.authenticated? -> true | false
+ *
+ * Indicated whether this Cipher instance uses an Authenticated Encryption
+ * mode.
+ */
+static VALUE
+ossl_cipher_is_authenticated(VALUE self)
+{
+ EVP_CIPHER_CTX *ctx;
+
+ GetCipher(self, ctx);
+
+#if defined(HAVE_AUTHENTICATED_ENCRYPTION)
+ return (EVP_CIPHER_CTX_flags(ctx) & EVP_CIPH_FLAG_AEAD_CIPHER) ? Qtrue : Qfalse;
+#else
+ return Qfalse;
+#endif
+}
+
#ifdef HAVE_AUTHENTICATED_ENCRYPTION
/*
* call-seq:
@@ -676,23 +694,6 @@ ossl_cipher_set_auth_tag_len(VALUE self, VALUE vlen)
}
/*
- * call-seq:
- * cipher.authenticated? -> boolean
- *
- * Indicated whether this Cipher instance uses an Authenticated Encryption
- * mode.
- */
-static VALUE
-ossl_cipher_is_authenticated(VALUE self)
-{
- EVP_CIPHER_CTX *ctx;
-
- GetCipher(self, ctx);
-
- return (EVP_CIPHER_CTX_flags(ctx) & EVP_CIPH_FLAG_AEAD_CIPHER) ? Qtrue : Qfalse;
-}
-
-/*
* call-seq:
* cipher.iv_len = integer -> integer
*
@@ -726,7 +727,6 @@ ossl_cipher_set_iv_length(VALUE self, VALUE iv_length)
#define ossl_cipher_get_auth_tag rb_f_notimplement
#define ossl_cipher_set_auth_tag rb_f_notimplement
#define ossl_cipher_set_auth_tag_len rb_f_notimplement
-#define ossl_cipher_is_authenticated rb_f_notimplement
#define ossl_cipher_set_iv_length rb_f_notimplement
#endif
@@ -939,12 +939,10 @@ Init_ossl_cipher(void)
* you absolutely need it</b>
*
* Because of this, you will end up with a mode that explicitly requires
- * an IV in any case. Note that for backwards compatibility reasons,
- * setting an IV is not explicitly mandated by the Cipher API. If not
- * set, OpenSSL itself defaults to an all-zeroes IV ("\\0", not the
- * character). Although the IV can be seen as public information, i.e.
- * it may be transmitted in public once generated, it should still stay
- * unpredictable to prevent certain kinds of attacks. Therefore, ideally
+ * an IV in any case. Although the IV can be seen as public information,
+ * i.e. it may be transmitted in public once generated, it should still
+ * stay unpredictable to prevent certain kinds of attacks. Therefore,
+ * ideally
*
* <b>Always create a secure random IV for every encryption of your
* Cipher</b>
@@ -1082,4 +1080,5 @@ Init_ossl_cipher(void)
rb_define_method(cCipher, "padding=", ossl_cipher_set_padding, 1);
id_auth_tag_len = rb_intern_const("auth_tag_len");
+ id_key_set = rb_intern_const("key_set");
}
diff --git a/ext/openssl/ossl_ns_spki.c b/ext/openssl/ossl_ns_spki.c
index 2f7845b6..98f6552e 100644
--- a/ext/openssl/ossl_ns_spki.c
+++ b/ext/openssl/ossl_ns_spki.c
@@ -159,8 +159,6 @@ ossl_spki_print(VALUE self)
{
NETSCAPE_SPKI *spki;
BIO *out;
- BUF_MEM *buf;
- VALUE str;
GetSPKI(self, spki);
if (!(out = BIO_new(BIO_s_mem()))) {
@@ -170,11 +168,8 @@ ossl_spki_print(VALUE self)
BIO_free(out);
ossl_raise(eSPKIError, NULL);
}
- BIO_get_mem_ptr(out, &buf);
- str = rb_str_new(buf->data, buf->length);
- BIO_free(out);
- return str;
+ return ossl_membio2str(out);
}
/*
diff --git a/ext/openssl/ossl_pkcs7.c b/ext/openssl/ossl_pkcs7.c
index fd58b48b..4040355f 100644
--- a/ext/openssl/ossl_pkcs7.c
+++ b/ext/openssl/ossl_pkcs7.c
@@ -795,7 +795,7 @@ ossl_pkcs7_verify(int argc, VALUE *argv, VALUE self)
BIO_free(in);
sk_X509_pop_free(x509s, X509_free);
if (ok < 0) ossl_raise(ePKCS7Error, "PKCS7_verify");
- msg = ERR_reason_error_string(ERR_get_error());
+ msg = ERR_reason_error_string(ERR_peek_error());
ossl_pkcs7_set_err_string(self, msg ? rb_str_new2(msg) : Qnil);
ossl_clear_error();
data = ossl_membio2str(out);
diff --git a/ext/openssl/ossl_pkey.c b/ext/openssl/ossl_pkey.c
index 2ce95b7c..9e6c6157 100644
--- a/ext/openssl/ossl_pkey.c
+++ b/ext/openssl/ossl_pkey.c
@@ -70,12 +70,12 @@ const rb_data_type_t ossl_evp_pkey_type = {
0, 0, RUBY_TYPED_FREE_IMMEDIATELY,
};
-VALUE
-ossl_pkey_new(EVP_PKEY *pkey)
+static VALUE
+pkey_new0(EVP_PKEY *pkey)
{
- if (!pkey) {
- ossl_raise(ePKeyError, "Cannot make new key from NULL.");
- }
+ if (!pkey)
+ ossl_raise(ePKeyError, "cannot make new key from NULL");
+
switch (EVP_PKEY_base_id(pkey)) {
#if !defined(OPENSSL_NO_RSA)
case EVP_PKEY_RSA:
@@ -96,29 +96,21 @@ ossl_pkey_new(EVP_PKEY *pkey)
default:
ossl_raise(ePKeyError, "unsupported key type");
}
-
- UNREACHABLE;
}
VALUE
-ossl_pkey_new_from_file(VALUE filename)
+ossl_pkey_new(EVP_PKEY *pkey)
{
- FILE *fp;
- EVP_PKEY *pkey;
-
- rb_check_safe_obj(filename);
- if (!(fp = fopen(StringValueCStr(filename), "r"))) {
- ossl_raise(ePKeyError, "%s", strerror(errno));
- }
- rb_fd_fix_cloexec(fileno(fp));
+ VALUE obj;
+ int status;
- pkey = PEM_read_PrivateKey(fp, NULL, ossl_pem_passwd_cb, NULL);
- fclose(fp);
- if (!pkey) {
- ossl_raise(ePKeyError, NULL);
+ obj = rb_protect((VALUE (*)(VALUE))pkey_new0, (VALUE)pkey, &status);
+ if (status) {
+ EVP_PKEY_free(pkey);
+ rb_jump_tag(status);
}
- return ossl_pkey_new(pkey);
+ return obj;
}
/*
@@ -303,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;
@@ -347,20 +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:
@@ -369,9 +373,8 @@ ossl_pkey_verify(VALUE self, VALUE digest, VALUE sig, VALUE data)
case 1:
return Qtrue;
default:
- ossl_raise(ePKeyError, NULL);
+ ossl_raise(ePKeyError, "EVP_VerifyFinal");
}
- return Qnil; /* dummy */
}
/*
diff --git a/ext/openssl/ossl_pkey.h b/ext/openssl/ossl_pkey.h
index 218f2ebb..e3b723cd 100644
--- a/ext/openssl/ossl_pkey.h
+++ b/ext/openssl/ossl_pkey.h
@@ -48,7 +48,6 @@ int ossl_generate_cb_2(int p, int n, BN_GENCB *cb);
void ossl_generate_cb_stop(void *ptr);
VALUE ossl_pkey_new(EVP_PKEY *);
-VALUE ossl_pkey_new_from_file(VALUE);
EVP_PKEY *GetPKeyPtr(VALUE);
EVP_PKEY *DupPKeyPtr(VALUE);
EVP_PKEY *GetPrivPKeyPtr(VALUE);
diff --git a/ext/openssl/ossl_pkey_dsa.c b/ext/openssl/ossl_pkey_dsa.c
index 3bce66f9..85085419 100644
--- a/ext/openssl/ossl_pkey_dsa.c
+++ b/ext/openssl/ossl_pkey_dsa.c
@@ -499,8 +499,6 @@ ossl_dsa_to_public_key(VALUE self)
return obj;
}
-#define ossl_dsa_buf_size(dsa) (DSA_size(dsa) + 16)
-
/*
* call-seq:
* dsa.syssign(string) -> aString
@@ -535,7 +533,7 @@ ossl_dsa_sign(VALUE self, VALUE data)
if (!DSA_PRIVATE(self, dsa))
ossl_raise(eDSAError, "Private DSA key needed!");
StringValue(data);
- str = rb_str_new(0, ossl_dsa_buf_size(dsa));
+ str = rb_str_new(0, DSA_size(dsa));
if (!DSA_sign(0, (unsigned char *)RSTRING_PTR(data), RSTRING_LENINT(data),
(unsigned char *)RSTRING_PTR(str),
&buf_len, dsa)) { /* type is ignored (0) */
diff --git a/ext/openssl/ossl_pkey_ec.c b/ext/openssl/ossl_pkey_ec.c
index f0a31231..5191c0f4 100644
--- a/ext/openssl/ossl_pkey_ec.c
+++ b/ext/openssl/ossl_pkey_ec.c
@@ -643,11 +643,10 @@ static VALUE ossl_ec_key_dsa_sign_asn1(VALUE self, VALUE data)
if (EC_KEY_get0_private_key(ec) == NULL)
ossl_raise(eECError, "Private EC key needed!");
- str = rb_str_new(0, ECDSA_size(ec) + 16);
+ str = rb_str_new(0, ECDSA_size(ec));
if (ECDSA_sign(0, (unsigned char *) RSTRING_PTR(data), RSTRING_LENINT(data), (unsigned char *) RSTRING_PTR(str), &buf_len, ec) != 1)
- ossl_raise(eECError, "ECDSA_sign");
-
- rb_str_resize(str, buf_len);
+ ossl_raise(eECError, "ECDSA_sign");
+ rb_str_set_len(str, buf_len);
return str;
}
@@ -1106,6 +1105,22 @@ static VALUE ossl_ec_group_get_point_conversion_form(VALUE self)
return ID2SYM(ret);
}
+static point_conversion_form_t
+parse_point_conversion_form_symbol(VALUE sym)
+{
+ ID id = SYM2ID(sym);
+
+ if (id == ID_uncompressed)
+ return POINT_CONVERSION_UNCOMPRESSED;
+ else if (id == ID_compressed)
+ return POINT_CONVERSION_COMPRESSED;
+ else if (id == ID_hybrid)
+ return POINT_CONVERSION_HYBRID;
+ else
+ ossl_raise(rb_eArgError, "unsupported point conversion form %+"PRIsVALUE
+ " (expected :compressed, :uncompressed, or :hybrid)", sym);
+}
+
/*
* call-seq:
* group.point_conversion_form = form
@@ -1125,23 +1140,14 @@ static VALUE ossl_ec_group_get_point_conversion_form(VALUE self)
*
* See the OpenSSL documentation for EC_GROUP_set_point_conversion_form()
*/
-static VALUE ossl_ec_group_set_point_conversion_form(VALUE self, VALUE form_v)
+static VALUE
+ossl_ec_group_set_point_conversion_form(VALUE self, VALUE form_v)
{
- EC_GROUP *group = NULL;
+ EC_GROUP *group;
point_conversion_form_t form;
- ID form_id = SYM2ID(form_v);
GetECGroup(self, group);
-
- if (form_id == ID_uncompressed) {
- form = POINT_CONVERSION_UNCOMPRESSED;
- } else if (form_id == ID_compressed) {
- form = POINT_CONVERSION_COMPRESSED;
- } else if (form_id == ID_hybrid) {
- form = POINT_CONVERSION_HYBRID;
- } else {
- ossl_raise(rb_eArgError, "form must be :compressed, :uncompressed, or :hybrid");
- }
+ form = parse_point_conversion_form_symbol(form_v);
EC_GROUP_set_point_conversion_form(group, form);
@@ -1191,7 +1197,7 @@ static VALUE ossl_ec_group_set_seed(VALUE self, VALUE seed)
/*
* call-seq:
- * group.degree => Fixnum
+ * group.degree => integer
*
* See the OpenSSL documentation for EC_GROUP_get_degree()
*/
@@ -1549,22 +1555,30 @@ static VALUE ossl_ec_point_set_to_infinity(VALUE self)
/*
* call-seq:
- * point.to_bn => OpenSSL::BN
+ * point.to_bn(conversion_form = nil) => OpenSSL::BN
+ *
+ * Convert the EC point into an octet string and store in an OpenSSL::BN. If
+ * +conversion_form+ is given, the point data is converted using the specified
+ * form. If not given, the default form set in the EC::Group object is used.
*
- * See the OpenSSL documentation for EC_POINT_point2bn()
+ * See also EC::Point#point_conversion_form=.
*/
-static VALUE ossl_ec_point_to_bn(VALUE self)
+static VALUE
+ossl_ec_point_to_bn(int argc, VALUE *argv, VALUE self)
{
EC_POINT *point;
- VALUE bn_obj;
+ VALUE form_obj, bn_obj;
const EC_GROUP *group;
point_conversion_form_t form;
BIGNUM *bn;
GetECPoint(self, point);
GetECPointGroup(self, group);
-
- form = EC_GROUP_get_point_conversion_form(group);
+ rb_scan_args(argc, argv, "01", &form_obj);
+ if (NIL_P(form_obj))
+ form = EC_GROUP_get_point_conversion_form(group);
+ else
+ form = parse_point_conversion_form_symbol(form_obj);
bn_obj = rb_obj_alloc(cBN);
bn = GetBNPtr(bn_obj);
@@ -1793,7 +1807,7 @@ void Init_ossl_ec(void)
rb_define_method(cEC_POINT, "set_to_infinity!", ossl_ec_point_set_to_infinity, 0);
/* all the other methods */
- rb_define_method(cEC_POINT, "to_bn", ossl_ec_point_to_bn, 0);
+ rb_define_method(cEC_POINT, "to_bn", ossl_ec_point_to_bn, -1);
rb_define_method(cEC_POINT, "mul", ossl_ec_point_mul, -1);
id_i_group = rb_intern("@group");
diff --git a/ext/openssl/ossl_pkey_rsa.c b/ext/openssl/ossl_pkey_rsa.c
index f969638a..cea228d6 100644
--- a/ext/openssl/ossl_pkey_rsa.c
+++ b/ext/openssl/ossl_pkey_rsa.c
@@ -404,8 +404,6 @@ ossl_rsa_to_der(VALUE self)
return str;
}
-#define ossl_rsa_buf_size(rsa) (RSA_size(rsa)+16)
-
/*
* call-seq:
* rsa.public_encrypt(string) => String
@@ -429,7 +427,7 @@ ossl_rsa_public_encrypt(int argc, VALUE *argv, VALUE self)
rb_scan_args(argc, argv, "11", &buffer, &padding);
pad = (argc == 1) ? RSA_PKCS1_PADDING : NUM2INT(padding);
StringValue(buffer);
- str = rb_str_new(0, ossl_rsa_buf_size(rsa));
+ str = rb_str_new(0, RSA_size(rsa));
buf_len = RSA_public_encrypt(RSTRING_LENINT(buffer), (unsigned char *)RSTRING_PTR(buffer),
(unsigned char *)RSTRING_PTR(str), rsa, pad);
if (buf_len < 0) ossl_raise(eRSAError, NULL);
@@ -461,7 +459,7 @@ ossl_rsa_public_decrypt(int argc, VALUE *argv, VALUE self)
rb_scan_args(argc, argv, "11", &buffer, &padding);
pad = (argc == 1) ? RSA_PKCS1_PADDING : NUM2INT(padding);
StringValue(buffer);
- str = rb_str_new(0, ossl_rsa_buf_size(rsa));
+ str = rb_str_new(0, RSA_size(rsa));
buf_len = RSA_public_decrypt(RSTRING_LENINT(buffer), (unsigned char *)RSTRING_PTR(buffer),
(unsigned char *)RSTRING_PTR(str), rsa, pad);
if (buf_len < 0) ossl_raise(eRSAError, NULL);
@@ -495,7 +493,7 @@ ossl_rsa_private_encrypt(int argc, VALUE *argv, VALUE self)
rb_scan_args(argc, argv, "11", &buffer, &padding);
pad = (argc == 1) ? RSA_PKCS1_PADDING : NUM2INT(padding);
StringValue(buffer);
- str = rb_str_new(0, ossl_rsa_buf_size(rsa));
+ str = rb_str_new(0, RSA_size(rsa));
buf_len = RSA_private_encrypt(RSTRING_LENINT(buffer), (unsigned char *)RSTRING_PTR(buffer),
(unsigned char *)RSTRING_PTR(str), rsa, pad);
if (buf_len < 0) ossl_raise(eRSAError, NULL);
@@ -529,7 +527,7 @@ ossl_rsa_private_decrypt(int argc, VALUE *argv, VALUE self)
rb_scan_args(argc, argv, "11", &buffer, &padding);
pad = (argc == 1) ? RSA_PKCS1_PADDING : NUM2INT(padding);
StringValue(buffer);
- str = rb_str_new(0, ossl_rsa_buf_size(rsa));
+ str = rb_str_new(0, RSA_size(rsa));
buf_len = RSA_private_decrypt(RSTRING_LENINT(buffer), (unsigned char *)RSTRING_PTR(buffer),
(unsigned char *)RSTRING_PTR(str), rsa, pad);
if (buf_len < 0) ossl_raise(eRSAError, NULL);
diff --git a/ext/openssl/ossl_ssl.c b/ext/openssl/ossl_ssl.c
index 861f820d..cf1502eb 100644
--- a/ext/openssl/ossl_ssl.c
+++ b/ext/openssl/ossl_ssl.c
@@ -11,10 +11,6 @@
*/
#include "ossl.h"
-#if defined(HAVE_UNISTD_H)
-# include <unistd.h> /* for read(), and write() */
-#endif
-
#define numberof(ary) (int)(sizeof(ary)/sizeof((ary)[0]))
#ifdef _WIN32
@@ -1496,19 +1492,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
diff --git a/ext/openssl/ossl_ssl_session.c b/ext/openssl/ossl_ssl_session.c
index fb7c0fb6..7abb8671 100644
--- a/ext/openssl/ossl_ssl_session.c
+++ b/ext/openssl/ossl_ssl_session.c
@@ -108,11 +108,7 @@ int SSL_SESSION_cmp(const SSL_SESSION *a,const SSL_SESSION *b)
if (a_len != b_len)
return 1;
-#if defined(_WIN32)
- return memcmp(a_sid, b_sid, a_len);
-#else
return CRYPTO_memcmp(a_sid, b_sid, a_len);
-#endif
}
#endif
@@ -141,19 +137,18 @@ static VALUE ossl_ssl_session_eq(VALUE val1, VALUE val2)
*
* Returns the time at which the session was established.
*/
-static VALUE ossl_ssl_session_get_time(VALUE self)
+static VALUE
+ossl_ssl_session_get_time(VALUE self)
{
- SSL_SESSION *ctx;
- time_t t;
-
- GetSSLSession(self, ctx);
-
- t = SSL_SESSION_get_time(ctx);
+ SSL_SESSION *ctx;
+ long t;
- if (t == 0)
- return Qnil;
+ GetSSLSession(self, ctx);
+ t = SSL_SESSION_get_time(ctx);
+ if (t == 0)
+ return Qnil;
- return rb_funcall(rb_cTime, rb_intern("at"), 1, TIMET2NUM(t));
+ return rb_funcall(rb_cTime, rb_intern("at"), 1, LONG2NUM(t));
}
/*
@@ -164,16 +159,16 @@ static VALUE ossl_ssl_session_get_time(VALUE self)
* established time.
*
*/
-static VALUE ossl_ssl_session_get_timeout(VALUE self)
+static VALUE
+ossl_ssl_session_get_timeout(VALUE self)
{
- SSL_SESSION *ctx;
- time_t t;
+ SSL_SESSION *ctx;
+ long t;
- GetSSLSession(self, ctx);
-
- t = SSL_SESSION_get_timeout(ctx);
+ GetSSLSession(self, ctx);
+ t = SSL_SESSION_get_timeout(ctx);
- return TIMET2NUM(t);
+ return LONG2NUM(t);
}
/*
@@ -270,9 +265,6 @@ static VALUE ossl_ssl_session_to_pem(VALUE self)
{
SSL_SESSION *ctx;
BIO *out;
- BUF_MEM *buf;
- VALUE str;
- int i;
GetSSLSession(self, ctx);
@@ -280,16 +272,13 @@ static VALUE ossl_ssl_session_to_pem(VALUE self)
ossl_raise(eSSLSession, "BIO_s_mem()");
}
- if (!(i=PEM_write_bio_SSL_SESSION(out, ctx))) {
+ if (!PEM_write_bio_SSL_SESSION(out, ctx)) {
BIO_free(out);
ossl_raise(eSSLSession, "SSL_SESSION_print()");
}
- BIO_get_mem_ptr(out, &buf);
- str = rb_str_new(buf->data, buf->length);
- BIO_free(out);
- return str;
+ return ossl_membio2str(out);
}
@@ -303,8 +292,6 @@ static VALUE ossl_ssl_session_to_text(VALUE self)
{
SSL_SESSION *ctx;
BIO *out;
- BUF_MEM *buf;
- VALUE str;
GetSSLSession(self, ctx);
@@ -317,11 +304,7 @@ static VALUE ossl_ssl_session_to_text(VALUE self)
ossl_raise(eSSLSession, "SSL_SESSION_print()");
}
- BIO_get_mem_ptr(out, &buf);
- str = rb_str_new(buf->data, buf->length);
- BIO_free(out);
-
- return str;
+ return ossl_membio2str(out);
}
diff --git a/ext/openssl/ossl_x509.h b/ext/openssl/ossl_x509.h
index c26da738..a60f7c3d 100644
--- a/ext/openssl/ossl_x509.h
+++ b/ext/openssl/ossl_x509.h
@@ -110,10 +110,13 @@ VALUE ossl_x509store_new(X509_STORE *);
X509_STORE *GetX509StorePtr(VALUE);
X509_STORE *DupX509StorePtr(VALUE);
-VALUE ossl_x509stctx_new(X509_STORE_CTX *);
-VALUE ossl_x509stctx_clear_ptr(VALUE);
X509_STORE_CTX *GetX509StCtxtPtr(VALUE);
-
void Init_ossl_x509store(void);
+/*
+ * Calls the verify callback Proc (the first parameter) with given pre-verify
+ * result and the X509_STORE_CTX.
+ */
+int ossl_verify_cb_call(VALUE, int, X509_STORE_CTX *);
+
#endif /* _OSSL_X509_H_ */
diff --git a/ext/openssl/ossl_x509cert.c b/ext/openssl/ossl_x509cert.c
index ad1126d4..cecc3ca0 100644
--- a/ext/openssl/ossl_x509cert.c
+++ b/ext/openssl/ossl_x509cert.c
@@ -624,7 +624,7 @@ ossl_x509_check_private_key(VALUE self, VALUE key)
pkey = GetPrivPKeyPtr(key); /* NO NEED TO DUP */
GetX509(self, x509);
if (!X509_check_private_key(x509, pkey)) {
- OSSL_Warning("Check private key:%s", OSSL_ErrMsg());
+ ossl_clear_error();
return Qfalse;
}
diff --git a/ext/openssl/ossl_x509crl.c b/ext/openssl/ossl_x509crl.c
index 0ff5d2f8..f9819f58 100644
--- a/ext/openssl/ossl_x509crl.c
+++ b/ext/openssl/ossl_x509crl.c
@@ -182,8 +182,6 @@ ossl_x509crl_get_signature_algorithm(VALUE self)
X509_CRL *crl;
const X509_ALGOR *alg;
BIO *out;
- BUF_MEM *buf;
- VALUE str;
GetX509CRL(self, crl);
if (!(out = BIO_new(BIO_s_mem()))) {
@@ -194,10 +192,8 @@ ossl_x509crl_get_signature_algorithm(VALUE self)
BIO_free(out);
ossl_raise(eX509CRLError, NULL);
}
- BIO_get_mem_ptr(out, &buf);
- str = rb_str_new(buf->data, buf->length);
- BIO_free(out);
- return str;
+
+ return ossl_membio2str(out);
}
static VALUE
@@ -388,8 +384,6 @@ ossl_x509crl_to_der(VALUE self)
{
X509_CRL *crl;
BIO *out;
- BUF_MEM *buf;
- VALUE str;
GetX509CRL(self, crl);
if (!(out = BIO_new(BIO_s_mem()))) {
@@ -399,11 +393,8 @@ ossl_x509crl_to_der(VALUE self)
BIO_free(out);
ossl_raise(eX509CRLError, NULL);
}
- BIO_get_mem_ptr(out, &buf);
- str = rb_str_new(buf->data, buf->length);
- BIO_free(out);
- return str;
+ return ossl_membio2str(out);
}
static VALUE
@@ -411,8 +402,6 @@ ossl_x509crl_to_pem(VALUE self)
{
X509_CRL *crl;
BIO *out;
- BUF_MEM *buf;
- VALUE str;
GetX509CRL(self, crl);
if (!(out = BIO_new(BIO_s_mem()))) {
@@ -422,11 +411,8 @@ ossl_x509crl_to_pem(VALUE self)
BIO_free(out);
ossl_raise(eX509CRLError, NULL);
}
- BIO_get_mem_ptr(out, &buf);
- str = rb_str_new(buf->data, buf->length);
- BIO_free(out);
- return str;
+ return ossl_membio2str(out);
}
static VALUE
@@ -434,8 +420,6 @@ ossl_x509crl_to_text(VALUE self)
{
X509_CRL *crl;
BIO *out;
- BUF_MEM *buf;
- VALUE str;
GetX509CRL(self, crl);
if (!(out = BIO_new(BIO_s_mem()))) {
@@ -445,11 +429,8 @@ ossl_x509crl_to_text(VALUE self)
BIO_free(out);
ossl_raise(eX509CRLError, NULL);
}
- BIO_get_mem_ptr(out, &buf);
- str = rb_str_new(buf->data, buf->length);
- BIO_free(out);
- return str;
+ return ossl_membio2str(out);
}
/*
diff --git a/ext/openssl/ossl_x509req.c b/ext/openssl/ossl_x509req.c
index d2619971..220d2f40 100644
--- a/ext/openssl/ossl_x509req.c
+++ b/ext/openssl/ossl_x509req.c
@@ -160,8 +160,6 @@ ossl_x509req_to_pem(VALUE self)
{
X509_REQ *req;
BIO *out;
- BUF_MEM *buf;
- VALUE str;
GetX509Req(self, req);
if (!(out = BIO_new(BIO_s_mem()))) {
@@ -171,11 +169,8 @@ ossl_x509req_to_pem(VALUE self)
BIO_free(out);
ossl_raise(eX509ReqError, NULL);
}
- BIO_get_mem_ptr(out, &buf);
- str = rb_str_new(buf->data, buf->length);
- BIO_free(out);
- return str;
+ return ossl_membio2str(out);
}
static VALUE
@@ -203,8 +198,6 @@ ossl_x509req_to_text(VALUE self)
{
X509_REQ *req;
BIO *out;
- BUF_MEM *buf;
- VALUE str;
GetX509Req(self, req);
if (!(out = BIO_new(BIO_s_mem()))) {
@@ -214,11 +207,8 @@ ossl_x509req_to_text(VALUE self)
BIO_free(out);
ossl_raise(eX509ReqError, NULL);
}
- BIO_get_mem_ptr(out, &buf);
- str = rb_str_new(buf->data, buf->length);
- BIO_free(out);
- return str;
+ return ossl_membio2str(out);
}
#if 0
@@ -304,8 +294,6 @@ ossl_x509req_get_signature_algorithm(VALUE self)
X509_REQ *req;
const X509_ALGOR *alg;
BIO *out;
- BUF_MEM *buf;
- VALUE str;
GetX509Req(self, req);
@@ -317,10 +305,8 @@ ossl_x509req_get_signature_algorithm(VALUE self)
BIO_free(out);
ossl_raise(eX509ReqError, NULL);
}
- BIO_get_mem_ptr(out, &buf);
- str = rb_str_new(buf->data, buf->length);
- BIO_free(out);
- return str;
+
+ return ossl_membio2str(out);
}
static VALUE
diff --git a/ext/openssl/ossl_x509store.c b/ext/openssl/ossl_x509store.c
index 75f8238b..eb81e0d4 100644
--- a/ext/openssl/ossl_x509store.c
+++ b/ext/openssl/ossl_x509store.c
@@ -48,6 +48,65 @@
} while (0)
/*
+ * Verify callback stuff
+ */
+static int stctx_ex_verify_cb_idx, store_ex_verify_cb_idx;
+static VALUE ossl_x509stctx_new(X509_STORE_CTX *);
+
+struct ossl_verify_cb_args {
+ VALUE proc;
+ VALUE preverify_ok;
+ VALUE store_ctx;
+};
+
+static VALUE
+call_verify_cb_proc(struct ossl_verify_cb_args *args)
+{
+ return rb_funcall(args->proc, rb_intern("call"), 2,
+ args->preverify_ok, args->store_ctx);
+}
+
+int
+ossl_verify_cb_call(VALUE proc, int ok, X509_STORE_CTX *ctx)
+{
+ VALUE rctx, ret;
+ struct ossl_verify_cb_args args;
+ int state;
+
+ if (NIL_P(proc))
+ return ok;
+
+ ret = Qfalse;
+ rctx = rb_protect((VALUE(*)(VALUE))ossl_x509stctx_new, (VALUE)ctx, &state);
+ if (state) {
+ rb_set_errinfo(Qnil);
+ rb_warn("StoreContext initialization failure");
+ }
+ else {
+ args.proc = proc;
+ args.preverify_ok = ok ? Qtrue : Qfalse;
+ args.store_ctx = rctx;
+ ret = rb_protect((VALUE(*)(VALUE))call_verify_cb_proc, (VALUE)&args, &state);
+ if (state) {
+ rb_set_errinfo(Qnil);
+ rb_warn("exception in verify_callback is ignored");
+ }
+ RTYPEDDATA_DATA(rctx) = NULL;
+ }
+ if (ret == Qtrue) {
+ X509_STORE_CTX_set_error(ctx, X509_V_OK);
+ ok = 1;
+ }
+ else {
+ if (X509_STORE_CTX_get_error(ctx) == X509_V_OK)
+ X509_STORE_CTX_set_error(ctx, X509_V_ERR_CERT_REJECTED);
+ ok = 0;
+ }
+
+ return ok;
+}
+
+/*
* Classes
*/
VALUE cX509Store;
@@ -111,9 +170,10 @@ x509store_verify_cb(int ok, X509_STORE_CTX *ctx)
{
VALUE proc;
- proc = (VALUE)X509_STORE_CTX_get_ex_data(ctx, ossl_store_ctx_ex_verify_cb_idx);
+ proc = (VALUE)X509_STORE_CTX_get_ex_data(ctx, stctx_ex_verify_cb_idx);
if (!proc)
- proc = (VALUE)X509_STORE_get_ex_data(X509_STORE_CTX_get0_store(ctx), ossl_store_ex_verify_cb_idx);
+ proc = (VALUE)X509_STORE_get_ex_data(X509_STORE_CTX_get0_store(ctx),
+ store_ex_verify_cb_idx);
if (!proc)
return ok;
@@ -144,7 +204,7 @@ ossl_x509store_set_vfy_cb(VALUE self, VALUE cb)
X509_STORE *store;
GetX509Store(self, store);
- X509_STORE_set_ex_data(store, ossl_store_ex_verify_cb_idx, (void *)cb);
+ X509_STORE_set_ex_data(store, store_ex_verify_cb_idx, (void *)cb);
rb_iv_set(self, "@verify_callback", cb);
return cb;
@@ -432,27 +492,6 @@ static const rb_data_type_t ossl_x509stctx_type = {
0, 0, RUBY_TYPED_FREE_IMMEDIATELY,
};
-
-VALUE
-ossl_x509stctx_new(X509_STORE_CTX *ctx)
-{
- VALUE obj;
-
- obj = NewX509StCtx(cX509StoreContext);
- SetX509StCtx(obj, ctx);
-
- return obj;
-}
-
-VALUE
-ossl_x509stctx_clear_ptr(VALUE obj)
-{
- OSSL_Check_Kind(obj, cX509StoreContext);
- RDATA(obj)->data = NULL;
-
- return obj;
-}
-
/*
* Private functions
*/
@@ -482,6 +521,17 @@ ossl_x509stctx_alloc(VALUE klass)
return obj;
}
+static VALUE
+ossl_x509stctx_new(X509_STORE_CTX *ctx)
+{
+ VALUE obj;
+
+ obj = NewX509StCtx(cX509StoreContext);
+ SetX509StCtx(obj, ctx);
+
+ return obj;
+}
+
static VALUE ossl_x509stctx_set_flags(VALUE, VALUE);
static VALUE ossl_x509stctx_set_purpose(VALUE, VALUE);
static VALUE ossl_x509stctx_set_trust(VALUE, VALUE);
@@ -527,7 +577,7 @@ ossl_x509stctx_verify(VALUE self)
X509_STORE_CTX *ctx;
GetX509StCtx(self, ctx);
- X509_STORE_CTX_set_ex_data(ctx, ossl_store_ctx_ex_verify_cb_idx,
+ X509_STORE_CTX_set_ex_data(ctx, stctx_ex_verify_cb_idx,
(void *)rb_iv_get(self, "@verify_callback"));
switch (X509_verify_cert(ctx)) {
@@ -747,6 +797,14 @@ Init_ossl_x509store(void)
mX509 = rb_define_module_under(mOSSL, "X509");
#endif
+ /* Register ext_data slot for verify callback Proc */
+ stctx_ex_verify_cb_idx = X509_STORE_CTX_get_ex_new_index(0, (void *)"stctx_ex_verify_cb_idx", 0, 0, 0);
+ if (stctx_ex_verify_cb_idx < 0)
+ ossl_raise(eOSSLError, "X509_STORE_CTX_get_ex_new_index");
+ store_ex_verify_cb_idx = X509_STORE_get_ex_new_index(0, (void *)"store_ex_verify_cb_idx", 0, 0, 0);
+ if (store_ex_verify_cb_idx < 0)
+ ossl_raise(eOSSLError, "X509_STORE_get_ex_new_index");
+
eX509StoreError = rb_define_class_under(mX509, "StoreError", eOSSLError);
/* Document-class: OpenSSL::X509::Store
diff --git a/ext/openssl/ruby_missing.h b/ext/openssl/ruby_missing.h
index f076b175..8dacc826 100644
--- a/ext/openssl/ruby_missing.h
+++ b/ext/openssl/ruby_missing.h
@@ -13,16 +13,7 @@
#define rb_define_copy_func(klass, func) \
rb_define_method((klass), "initialize_copy", (func), 1)
-
-#ifndef GetReadFile
#define FPTR_TO_FD(fptr) ((fptr)->fd)
-#else
-#define FPTR_TO_FD(fptr) (fileno(GetReadFile(fptr)))
-#endif
-
-#ifndef HAVE_RB_IO_T
-#define rb_io_t OpenFile
-#endif
#ifndef RB_INTEGER_TYPE_P
/* for Ruby 2.3 compatibility */
diff --git a/lib/openssl/buffering.rb b/lib/openssl/buffering.rb
index 61e1f43e..0db231f9 100644
--- a/lib/openssl/buffering.rb
+++ b/lib/openssl/buffering.rb
@@ -163,6 +163,10 @@ module OpenSSL::Buffering
# Note that one reason that read_nonblock writes to the underlying IO is
# when the peer requests a new TLS/SSL handshake. See openssl the FAQ for
# more details. http://www.openssl.org/support/faq.html
+ #
+ # By specifying `exception: false`, the options hash allows you to indicate
+ # that read_nonblock should not raise an IO::Wait*able exception, but
+ # return the symbol :wait_writable or :wait_readable instead.
def read_nonblock(maxlen, buf=nil, exception: true)
if maxlen == 0
@@ -371,6 +375,10 @@ module OpenSSL::Buffering
# Note that one reason that write_nonblock reads from the underlying IO
# is when the peer requests a new TLS/SSL handshake. See the openssl FAQ
# for more details. http://www.openssl.org/support/faq.html
+ #
+ # By specifying `exception: false`, the options hash allows you to indicate
+ # that write_nonblock should not raise an IO::Wait*able exception, but
+ # return the symbol :wait_writable or :wait_readable instead.
def write_nonblock(s, exception: true)
flush
diff --git a/openssl.gemspec b/openssl.gemspec
index 3080cb0a..e17811ad 100644
--- a/openssl.gemspec
+++ b/openssl.gemspec
@@ -17,8 +17,8 @@ Gem::Specification.new do |spec|
spec.required_ruby_version = ">= 2.3.0"
- spec.add_development_dependency "rake", "~> 10.3"
- spec.add_development_dependency "rake-compiler", "~> 0.9"
+ spec.add_development_dependency "rake"
+ spec.add_development_dependency "rake-compiler"
spec.add_development_dependency "test-unit", "~> 3.0"
- spec.add_development_dependency "rdoc", "~> 4.2"
+ spec.add_development_dependency "rdoc"
end
diff --git a/test/test_cipher.rb b/test/test_cipher.rb
index 74c5394f..8954cb66 100644
--- a/test/test_cipher.rb
+++ b/test/test_cipher.rb
@@ -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
-
- def has_ciphers?(list)
- list.all? { |name| has_cipher?(name) }
- end
-
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"
+ include Helper
+ extend Helper
+
+ 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 teardown
- super
- @c1 = @c2 = nil
- end
-
- 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")
+ 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
+
+ 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
+
+ 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
+ cipher = OpenSSL::Cipher.new('aes-128-cbc')
+ assert_not_predicate(cipher, :authenticated?)
+ end
- def test_aes_gcm_wrong_ciphertext
- pt = "You should all use Authenticated Encryption!"
- cipher, key, iv = new_encryptor('aes-128-gcm')
+ 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")
- cipher.auth_data = "aad"
- ct = cipher.update(pt) + cipher.final
- tag = cipher.auth_tag
+ def test_aes_ocb_tag_len
+ # 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*")
+
+ 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 = new_decryptor('aes-128-gcm', key, iv)
- decipher.auth_tag = tag
- decipher.auth_data = "aad"
+ end if has_cipher?("aes-128-ocb")
- assert_raise OpenSSL::Cipher::CipherError do
- decipher.update(ct[0..-2] << ct[-1].succ) + decipher.final
- end
- end
+ 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
- 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-gcm").encrypt
+ cipher.iv = "a" * 12
+ cipher.key = "x" * 16
+ ct2 = cipher.update(pt) << cipher.final
+ tag2 = cipher.auth_tag
- end
-
- 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)
-
- 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)
-
- 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")
+ 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
diff --git a/test/test_digest.rb b/test/test_digest.rb
index 51fc03bb..028889c1 100644
--- a/test/test_digest.rb
+++ b/test/test_digest.rb
@@ -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
diff --git a/test/test_hmac.rb b/test/test_hmac.rb
index dd58e4ac..dbde97d9 100644
--- a/test/test_hmac.rb
+++ b/test/test_hmac.rb
@@ -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)
-
- 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 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
+
+ # 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)
diff --git a/test/test_pair.rb b/test/test_pair.rb
index 7d962c38..5fbb77e7 100644
--- a/test/test_pair.rb
+++ b/test/test_pair.rb
@@ -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)
}
diff --git a/test/test_pkey.rb b/test/test_pkey.rb
deleted file mode 100644
index ba61fa26..00000000
--- a/test/test_pkey.rb
+++ /dev/null
@@ -1,56 +0,0 @@
-# frozen_string_literal: false
-require_relative "utils"
-
-if defined?(OpenSSL::TestUtils)
-
-class OpenSSL::TestPKey < OpenSSL::PKeyTestCase
- PKEYS = {
- OpenSSL::PKey::RSA => {
- key: OpenSSL::TestUtils::TEST_KEY_RSA1024,
- digest: OpenSSL::Digest::SHA1,
- },
- OpenSSL::PKey::DSA => {
- key: OpenSSL::TestUtils::TEST_KEY_DSA512,
- digest: OpenSSL::TestUtils::DSA_SIGNATURE_DIGEST,
- },
- }
- if defined?(OpenSSL::PKey::EC)
- PKEYS[OpenSSL::PKey::EC] = {
- key: OpenSSL::TestUtils::TEST_KEY_EC_P256V1,
- digest: OpenSSL::Digest::SHA1,
- }
- end
-
- def test_sign_verify
- data = "Sign me!"
- invalid_data = "Sign me?"
- PKEYS.each do |klass, prop|
- key = prop[:key]
- pub_key = dup_public(prop[:key])
- digest = prop[:digest].new
- signature = key.sign(digest, data)
- assert_equal(true, pub_key.verify(digest, signature, data))
- assert_equal(false, pub_key.verify(digest, signature, invalid_data))
- # digest state is irrelevant
- digest << "unya"
- assert_equal(true, pub_key.verify(digest, signature, data))
- assert_equal(false, pub_key.verify(digest, signature, invalid_data))
-
- if OpenSSL::OPENSSL_VERSION_NUMBER > 0x10000000
- digest = OpenSSL::Digest::SHA256.new
- signature = key.sign(digest, data)
- assert_equal(true, pub_key.verify(digest, signature, data))
- assert_equal(false, pub_key.verify(digest, signature, invalid_data))
- end
- end
- end
-
- def test_verify_empty_rsa
- rsa = OpenSSL::PKey::RSA.new
- assert_raise(OpenSSL::PKey::PKeyError, "[Bug #12783]") {
- rsa.verify("SHA1", "a", "b")
- }
- end
-end
-
-end
diff --git a/test/test_pkey_dsa.rb b/test/test_pkey_dsa.rb
index d0ba8ec0..a4ccd1d8 100644
--- a/test/test_pkey_dsa.rb
+++ b/test/test_pkey_dsa.rb
@@ -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!'
diff --git a/test/test_pkey_ec.rb b/test/test_pkey_ec.rb
index 53aa5a10..e281f80c 100644
--- a/test/test_pkey_ec.rb
+++ b/test/test_pkey_ec.rb
@@ -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
diff --git a/test/test_pkey_rsa.rb b/test/test_pkey_rsa.rb
index e211faa6..b24f1d55 100644
--- a/test/test_pkey_rsa.rb
+++ b/test/test_pkey_rsa.rb
@@ -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),
diff --git a/test/test_x509name.rb b/test/test_x509name.rb
index 250f1d09..78da4df1 100644
--- a/test/test_x509name.rb
+++ b/test/test_x509name.rb
@@ -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
diff --git a/test/utils.rb b/test/utils.rb
index 6f3a3c6d..0016f5c7 100644
--- a/test/utils.rb
+++ b/test/utils.rb
@@ -10,7 +10,6 @@ rescue LoadError
end
require "test/unit"
-require "digest/md5"
require 'tempfile'
require "rbconfig"
require "socket"
diff --git a/tool/ruby-openssl-docker/Dockerfile b/tool/ruby-openssl-docker/Dockerfile
index 4ecc3936..a1518a9c 100644
--- a/tool/ruby-openssl-docker/Dockerfile
+++ b/tool/ruby-openssl-docker/Dockerfile
@@ -28,51 +28,45 @@ RUN curl -s https://www.openssl.org/source/openssl-1.0.0t.tar.gz | tar -C /build
shared debug-linux-x86_64 && \
make && make install_sw
-RUN curl -s https://www.openssl.org/source/openssl-1.0.1t.tar.gz | tar -C /build/openssl -xzf - && \
- cd /build/openssl/openssl-1.0.1t && \
+RUN curl -s https://www.openssl.org/source/openssl-1.0.1u.tar.gz | tar -C /build/openssl -xzf - && \
+ cd /build/openssl/openssl-1.0.1u && \
./Configure \
--openssldir=/opt/openssl/openssl-1.0.1 \
shared debug-linux-x86_64 && \
make && make install_sw
-RUN curl -s https://www.openssl.org/source/openssl-1.0.2h.tar.gz | tar -C /build/openssl -xzf - && \
- cd /build/openssl/openssl-1.0.2h && \
+RUN curl -s https://www.openssl.org/source/openssl-1.0.2j.tar.gz | tar -C /build/openssl -xzf - && \
+ cd /build/openssl/openssl-1.0.2j && \
./Configure \
--openssldir=/opt/openssl/openssl-1.0.2 \
shared debug-linux-x86_64 && \
make && make install_sw
-RUN curl -s https://www.openssl.org/source/openssl-1.1.0.tar.gz | tar -C /build/openssl -xzf - && \
- cd /build/openssl/openssl-1.1.0 && \
+RUN curl -s https://www.openssl.org/source/openssl-1.1.0b.tar.gz | tar -C /build/openssl -xzf - && \
+ cd /build/openssl/openssl-1.1.0b && \
./Configure \
--prefix=/opt/openssl/openssl-1.1.0 \
enable-crypto-mdebug enable-crypto-mdebug-backtrace \
debug-linux-x86_64 && \
make && make install_sw
-# Supported libressl versions: 2.1, 2.2, 2.3, 2.4
-RUN curl -s http://ftp.openbsd.org/pub/OpenBSD/LibreSSL/libressl-2.1.10.tar.gz | tar -C /build/openssl -xzf -
-RUN cd /build/openssl/libressl-2.1.10 && \
+# Supported libressl versions: 2.3, 2.4, 2.5
+RUN curl -s http://ftp.openbsd.org/pub/OpenBSD/LibreSSL/libressl-2.3.8.tar.gz | tar -C /build/openssl -xzf -
+RUN cd /build/openssl/libressl-2.3.8 && \
./configure \
- --prefix=/opt/openssl/libressl-2.1 && \
- make && make install
-
-RUN curl -s http://ftp.openbsd.org/pub/OpenBSD/LibreSSL/libressl-2.2.9.tar.gz | tar -C /build/openssl -xzf -
-RUN cd /build/openssl/libressl-2.2.9 && \
- ./configure \
- --prefix=/opt/openssl/libressl-2.2 && \
+ --prefix=/opt/openssl/libressl-2.3 && \
make && make install
-RUN curl -s http://ftp.openbsd.org/pub/OpenBSD/LibreSSL/libressl-2.3.7.tar.gz | tar -C /build/openssl -xzf -
-RUN cd /build/openssl/libressl-2.3.7 && \
+RUN curl -s http://ftp.openbsd.org/pub/OpenBSD/LibreSSL/libressl-2.4.3.tar.gz | tar -C /build/openssl -xzf -
+RUN cd /build/openssl/libressl-2.4.3 && \
./configure \
- --prefix=/opt/openssl/libressl-2.3 && \
+ --prefix=/opt/openssl/libressl-2.4 && \
make && make install
-RUN curl -s http://ftp.openbsd.org/pub/OpenBSD/LibreSSL/libressl-2.4.2.tar.gz | tar -C /build/openssl -xzf -
-RUN cd /build/openssl/libressl-2.4.2 && \
+RUN curl -s http://ftp.openbsd.org/pub/OpenBSD/LibreSSL/libressl-2.5.0.tar.gz | tar -C /build/openssl -xzf -
+RUN cd /build/openssl/libressl-2.5.0 && \
./configure \
- --prefix=/opt/openssl/libressl-2.4 && \
+ --prefix=/opt/openssl/libressl-2.5 && \
make && make install
# Supported Ruby versions: 2.3
diff --git a/tool/ruby-openssl-docker/README.md b/tool/ruby-openssl-docker/README.md
index 5211dd77..93c75ed3 100644
--- a/tool/ruby-openssl-docker/README.md
+++ b/tool/ruby-openssl-docker/README.md
@@ -1,5 +1,6 @@
# ruby-openssl-docker
-Supports OpenSSL 1.0.0t, 1.0.1q, 1.0.2e and LibreSSL 2.1.9, 2.2.5 and 2.3.1.
+Docker image for testing. The image contains various binaries of supported
+versions of OpenSSL, LibreSSL, and Ruby.
-Currently only Ruby 2.3.0 is supported.
+CONTRIBUTING.md on the top directory describes how to use the image.
diff --git a/tool/ruby-openssl-docker/init.sh b/tool/ruby-openssl-docker/init.sh
index 3fa271c4..c4301482 100755
--- a/tool/ruby-openssl-docker/init.sh
+++ b/tool/ruby-openssl-docker/init.sh
@@ -15,15 +15,6 @@ export PATH="/opt/ruby/${RUBY_VERSION}/bin:$PATH"
export LD_LIBRARY_PATH="/opt/openssl/${OPENSSL_VERSION}/lib"
export PKG_CONFIG_PATH="/opt/openssl/${OPENSSL_VERSION}/lib/pkgconfig"
-ruby -e '
- newsource = Gem::Source.new("http://rubygems.org")
- Gem.sources.replace([newsource])
- Gem.configuration.write
-
- spec = eval(File.read("openssl.gemspec"))
- spec.development_dependencies.each do |dep|
- Gem.install(dep.name, dep.requirement, force: true)
- end
-'
+rake install_dependencies USE_HTTP_RUBYGEMS_ORG=1
exec $*