diff options
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 ``` @@ -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 @@ -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 @@ -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 $* |