aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKazuki Yamaguchi <k@rhe.jp>2016-05-31 11:31:27 +0900
committerKazuki Yamaguchi <k@rhe.jp>2016-05-31 11:31:27 +0900
commit478c74340f9ea91d6b18a1c4836a4edb2357c9dc (patch)
tree86d78a22548b105273054941c4a5d1daeabc1a5f
parent1cc7eea683044c0c295a6fdb05e848cc6554e361 (diff)
parent2293533fec90b4adc5368f2fd1ef0fec0832b2f4 (diff)
downloadruby-openssl-478c74340f9ea91d6b18a1c4836a4edb2357c9dc.tar.gz
Merge changes from Ruby trunk r53718..r55224
* ruby-trunk r53718..r55224: (46 commits) (r55224) openssl: fix test failure on Fedora 23 (r55219) openssl: use NUM2TIMET() to convert Integer to time_t (r55214) openssl: add SSLContext#ecdh_curves= (r55191) openssl: move SSLSocket#initialize to C extension (r55175) openssl: avoid NULL dereference in {DH,DSA,RSA}_size() (r55162) openssl: drop OpenSSL 0.9.6/0.9.7 support (r55161) openssl: remove unnecessary 'extern "C"' blocks from local .. (r55160) openssl: remove check of OPENSSL_FIPS macro in extconf.rb (r55152) openssl: add EC.generate (r55151) openssl: rename EC#generate_key to EC#generate_key! (r55146) openssl: make Cipher#key= and #iv= reject too long values (r55145) openssl: avoid deprecated M_ASN1_* macros (r55135) openssl: Avoid reference to unset global variable in Init_o.. (r55134) openssl: use StringValueCStr() where NUL-terminated string .. (r55132) openssl: fix incorrect return value check of RAND_* functions (r55100) openssl: fix possible SEGV on race between SSLSocket#stop a.. (r55099) openssl: fix SSL client example in documentation [ci skip] (r55098) openssl: add OpenSSL::PKey::EC#private? and #public? (r55097) openssl: remove impossible EOFError raise in OpenSSL::Buffe.. (r55089) ossl.c: suppress warnings (r55087) openssl: improve handling of password for encrypted PEM (r55078) openssl: don't test default session lifetime value (r55074) openssl: register ex_data index for X509_STORE{_CTX,} respe.. (r55071) openssl: check argument type in OpenSSL::X509::Attribute#va.. (r55060) openssl: fix test failure due to the previous commit (r55059) openssl: fix test failure of OpenSSL::TestEC#test_ec_point_.. (r55058) test_random.rb: skip old OpenSSL (r55057) openssl: fix OpenSSL error queue leak in OpenSSL::PKCS12.new (r55056) openssl/test_random.rb: requires utils.rb (r55052) ossl_pkey_ec.c: index types (r55051) openssl: clear OpenSSL error queue before return to Ruby (r55050) openssl: report errors in OpenSSL error queue when clear it (r55048) ext/openssl: refactor OpenSSL::PKey::EC::Point#mul (r55047) openssl: fix equality test methods of OpenSSL::BN (r55029) Use Integer instead of Fixnum and Bignum. (r54959) openssl/extconf.rb: NO SSL macros first (r54950) * ext/openssl/extconf.rb: asume it doesn't have SSLv2 relat.. (r54506) test_ssl.rb: skip unsupported ciphers (r54498) test_ssl.rb: skip unavailable pkeys (r54487) test_get_ephemeral_key: use assert_instance_of (r54485) openssl: Access to ephemeral TLS session key (r54466) openssl: accept moving write buffer for write_nonblock (r54258) openssl: fix build when NPN is disabled by OpenSSL (r54097) document OpenSSL::SSL::SSLContext#setup as MT-unsafe (r53871) test: use assert_not_* (r53723) Fix typo on OpenSSL::PKey doc [ci skip] Sync-with-trunk: r55224
-rw-r--r--ext/openssl/deprecation.rb8
-rw-r--r--ext/openssl/extconf.rb138
-rw-r--r--ext/openssl/openssl_missing.c353
-rw-r--r--ext/openssl/openssl_missing.h184
-rw-r--r--ext/openssl/ossl.c117
-rw-r--r--ext/openssl/ossl.h55
-rw-r--r--ext/openssl/ossl_asn1.c94
-rw-r--r--ext/openssl/ossl_bn.c101
-rw-r--r--ext/openssl/ossl_cipher.c28
-rw-r--r--ext/openssl/ossl_digest.c2
-rw-r--r--ext/openssl/ossl_engine.c58
-rw-r--r--ext/openssl/ossl_ns_spki.c6
-rw-r--r--ext/openssl/ossl_ocsp.c4
-rw-r--r--ext/openssl/ossl_ocsp.h2
-rw-r--r--ext/openssl/ossl_pkcs12.c18
-rw-r--r--ext/openssl/ossl_pkcs5.c4
-rw-r--r--ext/openssl/ossl_pkcs7.c31
-rw-r--r--ext/openssl/ossl_pkey.c45
-rw-r--r--ext/openssl/ossl_pkey.h4
-rw-r--r--ext/openssl/ossl_pkey_dh.c19
-rw-r--r--ext/openssl/ossl_pkey_dsa.c55
-rw-r--r--ext/openssl/ossl_pkey_ec.c328
-rw-r--r--ext/openssl/ossl_pkey_rsa.c45
-rw-r--r--ext/openssl/ossl_rand.c25
-rw-r--r--ext/openssl/ossl_ssl.c459
-rw-r--r--ext/openssl/ossl_ssl.h3
-rw-r--r--ext/openssl/ossl_ssl_session.c9
-rw-r--r--ext/openssl/ossl_x509.c10
-rw-r--r--ext/openssl/ossl_x509attr.c19
-rw-r--r--ext/openssl/ossl_x509cert.c19
-rw-r--r--ext/openssl/ossl_x509crl.c14
-rw-r--r--ext/openssl/ossl_x509ext.c36
-rw-r--r--ext/openssl/ossl_x509req.c14
-rw-r--r--ext/openssl/ossl_x509store.c57
-rw-r--r--lib/openssl/buffering.rb2
-rw-r--r--lib/openssl/ssl.rb55
-rw-r--r--test/test_asn1.rb2
-rw-r--r--test/test_bn.rb18
-rw-r--r--test/test_buffering.rb10
-rw-r--r--test/test_cipher.rb85
-rw-r--r--test/test_config.rb3
-rw-r--r--test/test_digest.rb3
-rw-r--r--test/test_engine.rb3
-rw-r--r--test/test_fips.rb2
-rw-r--r--test/test_hmac.rb5
-rw-r--r--test/test_ns_spki.rb2
-rw-r--r--test/test_ocsp.rb2
-rw-r--r--test/test_pair.rb128
-rw-r--r--test/test_pkcs12.rb2
-rw-r--r--test/test_pkcs5.rb2
-rw-r--r--test/test_pkcs7.rb8
-rw-r--r--test/test_pkey_dh.rb2
-rw-r--r--test/test_pkey_dsa.rb24
-rw-r--r--test/test_pkey_ec.rb101
-rw-r--r--test/test_pkey_rsa.rb29
-rw-r--r--test/test_random.rb9
-rw-r--r--test/test_ssl.rb63
-rw-r--r--test/test_ssl_session.rb16
-rw-r--r--test/test_x509attr.rb56
-rw-r--r--test/test_x509cert.rb5
-rw-r--r--test/test_x509crl.rb5
-rw-r--r--test/test_x509ext.rb5
-rw-r--r--test/test_x509name.rb5
-rw-r--r--test/test_x509req.rb2
-rw-r--r--test/test_x509store.rb7
-rw-r--r--test/utils.rb13
66 files changed, 1471 insertions, 1567 deletions
diff --git a/ext/openssl/deprecation.rb b/ext/openssl/deprecation.rb
index d7735367..7dfc87c1 100644
--- a/ext/openssl/deprecation.rb
+++ b/ext/openssl/deprecation.rb
@@ -16,7 +16,11 @@ module OpenSSL
end
def self.check_func(func, header)
- have_func(func, header, deprecated_warning_flag) and
- have_header(header, nil, deprecated_warning_flag)
+ have_func(func, header, deprecated_warning_flag)
+ end
+
+ def self.check_func_or_macro(func, header)
+ check_func(func, header) or
+ have_macro(func, header) && $defs.push("-DHAVE_#{func.upcase}")
end
end
diff --git a/ext/openssl/extconf.rb b/ext/openssl/extconf.rb
index 7bb6cd8f..eeeae448 100644
--- a/ext/openssl/extconf.rb
+++ b/ext/openssl/extconf.rb
@@ -19,12 +19,15 @@ dir_config("kerberos")
Logging::message "=== OpenSSL for Ruby configurator ===\n"
+# Add -Werror=deprecated-declarations to $warnflags if available
+OpenSSL.deprecated_warning_flag
+
##
# Adds -DOSSL_DEBUG for compilation and some more targets when GCC is used
# To turn it on, use: --with-debug or --enable-debug
#
if with_config("debug") or enable_config("debug")
- $defs.push("-DOSSL_DEBUG") unless $defs.include? "-DOSSL_DEBUG"
+ $defs.push("-DOSSL_DEBUG")
end
Logging::message "=== Checking for system dependent stuff... ===\n"
@@ -39,7 +42,6 @@ if $mingw
end
result = pkg_config("openssl") && have_header("openssl/ssl.h")
-
unless result
result = have_header("openssl/ssl.h")
result &&= %w[crypto libeay32].any? {|lib| have_library(lib, "OpenSSL_add_all_digests")}
@@ -51,107 +53,63 @@ unless result
end
end
-unless have_header("openssl/conf_api.h")
- raise "OpenSSL 0.9.6 or later required."
+result = checking_for("OpenSSL version is 0.9.8 or later") {
+ try_static_assert("OPENSSL_VERSION_NUMBER >= 0x00908000L", "openssl/opensslv.h")
+}
+unless result
+ raise "OpenSSL 0.9.8 or later required."
end
+
unless OpenSSL.check_func("SSL_library_init()", "openssl/ssl.h")
raise "Ignore OpenSSL broken by Apple.\nPlease use another openssl. (e.g. using `configure --with-openssl-dir=/path/to/openssl')"
end
Logging::message "=== Checking for OpenSSL features... ===\n"
-have_func("ERR_peek_last_error")
-have_func("ASN1_put_eoc")
-have_func("BN_mod_add")
-have_func("BN_mod_sqr")
-have_func("BN_mod_sub")
-have_func("BN_pseudo_rand_range")
-have_func("BN_rand_range")
-have_func("CONF_get1_default_config_file")
+# compile options
+
+# check OPENSSL_NO_{SSL2,SSL3_METHOD} macro: on some environment, these symbols
+# exist even if compiled with no-ssl2 or no-ssl3-method.
+unless have_macro("OPENSSL_NO_SSL2", "openssl/opensslconf.h")
+ have_func("SSLv2_method")
+end
+unless have_macro("OPENSSL_NO_SSL3_METHOD", "openssl/opensslconf.h")
+ have_func("SSLv3_method")
+end
+have_func("TLSv1_1_method")
+have_func("TLSv1_2_method")
+have_func("RAND_egd")
+engines = %w{builtin_engines openbsd_dev_crypto dynamic 4758cca aep atalla chil
+ cswift nuron sureware ubsec padlock capi gmp gost cryptodev aesni}
+engines.each { |name|
+ OpenSSL.check_func_or_macro("ENGINE_load_#{name}", "openssl/engine.h")
+}
+
+# added in 1.0.0
have_func("EVP_CIPHER_CTX_copy")
-have_func("EVP_CIPHER_CTX_set_padding")
-have_func("EVP_CipherFinal_ex")
-have_func("EVP_CipherInit_ex")
-have_func("EVP_DigestFinal_ex")
-have_func("EVP_DigestInit_ex")
-have_func("EVP_MD_CTX_cleanup")
-have_func("EVP_MD_CTX_create")
-have_func("EVP_MD_CTX_destroy")
-have_func("EVP_MD_CTX_init")
-have_func("HMAC_CTX_cleanup")
have_func("HMAC_CTX_copy")
-have_func("HMAC_CTX_init")
-have_func("PEM_def_callback")
have_func("PKCS5_PBKDF2_HMAC")
-have_func("PKCS5_PBKDF2_HMAC_SHA1")
-have_func("RAND_egd")
-have_func("X509V3_set_nconf")
-have_func("X509V3_EXT_nconf_nid")
-have_func("X509_CRL_add0_revoked")
-have_func("X509_CRL_set_issuer_name")
-have_func("X509_CRL_set_version")
-have_func("X509_CRL_sort")
have_func("X509_NAME_hash_old")
-have_func("X509_STORE_get_ex_data")
-have_func("X509_STORE_set_ex_data")
-have_func("OBJ_NAME_do_all_sorted")
-have_func("SSL_SESSION_get_id")
-have_func("SSL_SESSION_cmp")
-have_func("OPENSSL_cleanse")
-have_func("SSLv2_method")
-have_func("SSLv2_server_method")
-have_func("SSLv2_client_method")
-have_func("SSLv3_method")
-have_func("SSLv3_server_method")
-have_func("SSLv3_client_method")
-have_func("TLSv1_1_method")
-have_func("TLSv1_1_server_method")
-have_func("TLSv1_1_client_method")
-have_func("TLSv1_2_method")
-have_func("TLSv1_2_server_method")
-have_func("TLSv1_2_client_method")
-have_func("SSL_CTX_set_alpn_select_cb")
-have_macro("OPENSSL_NPN_NEGOTIATED", ['openssl/ssl.h']) && $defs.push("-DHAVE_OPENSSL_NPN_NEGOTIATED")
-unless have_func("SSL_set_tlsext_host_name", ['openssl/ssl.h'])
- have_macro("SSL_set_tlsext_host_name", ['openssl/ssl.h']) && $defs.push("-DHAVE_SSL_SET_TLSEXT_HOST_NAME")
-end
-if have_header("openssl/engine.h")
- have_func("ENGINE_add")
- have_func("ENGINE_load_builtin_engines")
- have_func("ENGINE_load_openbsd_dev_crypto")
- have_func("ENGINE_get_digest")
- have_func("ENGINE_get_cipher")
- have_func("ENGINE_cleanup")
- have_func("ENGINE_load_dynamic")
- have_func("ENGINE_load_4758cca")
- have_func("ENGINE_load_aep")
- have_func("ENGINE_load_atalla")
- have_func("ENGINE_load_chil")
- have_func("ENGINE_load_cswift")
- have_func("ENGINE_load_nuron")
- have_func("ENGINE_load_sureware")
- have_func("ENGINE_load_ubsec")
- have_func("ENGINE_load_padlock")
- have_func("ENGINE_load_capi")
- have_func("ENGINE_load_gmp")
- have_func("ENGINE_load_gost")
- have_func("ENGINE_load_cryptodev")
- have_func("ENGINE_load_aesni")
-end
-have_func("DH_generate_parameters_ex")
-have_func("DSA_generate_parameters_ex")
-have_func("RSA_generate_key_ex")
-if checking_for('OpenSSL version is 0.9.7 or later') {
- try_static_assert('OPENSSL_VERSION_NUMBER >= 0x00907000L', 'openssl/opensslv.h')
- }
- have_header("openssl/ocsp.h")
-end
+have_func("SSL_SESSION_cmp") # removed
+OpenSSL.check_func_or_macro("SSL_set_tlsext_host_name", "openssl/ssl.h")
have_struct_member("CRYPTO_THREADID", "ptr", "openssl/crypto.h")
-have_struct_member("EVP_CIPHER_CTX", "flags", "openssl/evp.h")
-have_struct_member("EVP_CIPHER_CTX", "engine", "openssl/evp.h")
-have_struct_member("X509_ATTRIBUTE", "single", "openssl/x509.h")
-have_macro("OPENSSL_FIPS", ['openssl/opensslconf.h']) && $defs.push("-DHAVE_OPENSSL_FIPS")
+
+# added in 1.0.1
+have_func("SSL_CTX_set_next_proto_select_cb")
have_macro("EVP_CTRL_GCM_GET_TAG", ['openssl/evp.h']) && $defs.push("-DHAVE_AUTHENTICATED_ENCRYPTION")
+# added in 1.0.2
+have_func("EC_curve_nist2nid")
+have_func("X509_REVOKED_dup")
+have_func("SSL_CTX_set_alpn_select_cb")
+OpenSSL.check_func_or_macro("SSL_CTX_set1_curves_list", "openssl/ssl.h")
+OpenSSL.check_func_or_macro("SSL_CTX_set_ecdh_auto", "openssl/ssl.h")
+OpenSSL.check_func_or_macro("SSL_get_server_tmp_key", "openssl/ssl.h")
+
+# added in 1.1.0
+have_func("X509_STORE_get_ex_data")
+have_func("X509_STORE_set_ex_data")
+OpenSSL.check_func_or_macro("SSL_CTX_set_tmp_ecdh_callback", "openssl/ssl.h") # removed
+
Logging::message "=== Checking done. ===\n"
create_header
diff --git a/ext/openssl/openssl_missing.c b/ext/openssl/openssl_missing.c
index bd8eef5e..796d8aa0 100644
--- a/ext/openssl/openssl_missing.c
+++ b/ext/openssl/openssl_missing.c
@@ -9,107 +9,18 @@
*/
#include RUBY_EXTCONF_H
-#if defined(HAVE_OPENSSL_ENGINE_H) && defined(HAVE_EVP_CIPHER_CTX_ENGINE)
+#include <string.h> /* memcpy() */
+#if !defined(OPENSSL_NO_ENGINE)
# include <openssl/engine.h>
#endif
-#include <openssl/x509_vfy.h>
-
#if !defined(OPENSSL_NO_HMAC)
-#include <string.h> /* memcpy() */
-#include <openssl/hmac.h>
-
-#include "openssl_missing.h"
-
-#if !defined(HAVE_HMAC_CTX_COPY)
-void
-HMAC_CTX_copy(HMAC_CTX *out, HMAC_CTX *in)
-{
- if (!out || !in) return;
- memcpy(out, in, sizeof(HMAC_CTX));
-
- EVP_MD_CTX_copy(&out->md_ctx, &in->md_ctx);
- EVP_MD_CTX_copy(&out->i_ctx, &in->i_ctx);
- EVP_MD_CTX_copy(&out->o_ctx, &in->o_ctx);
-}
-#endif /* HAVE_HMAC_CTX_COPY */
-#endif /* NO_HMAC */
-
-#if !defined(HAVE_X509_STORE_SET_EX_DATA)
-int X509_STORE_set_ex_data(X509_STORE *str, int idx, void *data)
-{
- return CRYPTO_set_ex_data(&str->ex_data, idx, data);
-}
-#endif
-
-#if !defined(HAVE_X509_STORE_GET_EX_DATA)
-void *X509_STORE_get_ex_data(X509_STORE *str, int idx)
-{
- return CRYPTO_get_ex_data(&str->ex_data, idx);
-}
-#endif
-
-#if !defined(HAVE_EVP_MD_CTX_CREATE)
-EVP_MD_CTX *
-EVP_MD_CTX_create(void)
-{
- EVP_MD_CTX *ctx = OPENSSL_malloc(sizeof(EVP_MD_CTX));
- if (!ctx) return NULL;
-
- memset(ctx, 0, sizeof(EVP_MD_CTX));
-
- return ctx;
-}
-#endif
-
-#if !defined(HAVE_EVP_MD_CTX_CLEANUP)
-int
-EVP_MD_CTX_cleanup(EVP_MD_CTX *ctx)
-{
- /* FIXME!!! */
- memset(ctx, 0, sizeof(EVP_MD_CTX));
-
- return 1;
-}
-#endif
-
-#if !defined(HAVE_EVP_MD_CTX_DESTROY)
-void
-EVP_MD_CTX_destroy(EVP_MD_CTX *ctx)
-{
- EVP_MD_CTX_cleanup(ctx);
- OPENSSL_free(ctx);
-}
-#endif
-
-#if !defined(HAVE_EVP_MD_CTX_INIT)
-void
-EVP_MD_CTX_init(EVP_MD_CTX *ctx)
-{
- memset(ctx, 0, sizeof(EVP_MD_CTX));
-}
-#endif
-
-#if !defined(HAVE_HMAC_CTX_INIT)
-void
-HMAC_CTX_init(HMAC_CTX *ctx)
-{
- EVP_MD_CTX_init(&ctx->i_ctx);
- EVP_MD_CTX_init(&ctx->o_ctx);
- EVP_MD_CTX_init(&ctx->md_ctx);
-}
+# include <openssl/hmac.h>
#endif
+#include <openssl/x509_vfy.h>
-#if !defined(HAVE_HMAC_CTX_CLEANUP)
-void
-HMAC_CTX_cleanup(HMAC_CTX *ctx)
-{
- EVP_MD_CTX_cleanup(&ctx->i_ctx);
- EVP_MD_CTX_cleanup(&ctx->o_ctx);
- EVP_MD_CTX_cleanup(&ctx->md_ctx);
- memset(ctx, 0, sizeof(HMAC_CTX));
-}
-#endif
+#include "openssl_missing.h"
+/* added in 1.0.0 */
#if !defined(HAVE_EVP_CIPHER_CTX_COPY)
/*
* this function does not exist in OpenSSL yet... or ever?.
@@ -117,11 +28,11 @@ HMAC_CTX_cleanup(HMAC_CTX *ctx)
* tested on 0.9.7d.
*/
int
-EVP_CIPHER_CTX_copy(EVP_CIPHER_CTX *out, EVP_CIPHER_CTX *in)
+EVP_CIPHER_CTX_copy(EVP_CIPHER_CTX *out, const EVP_CIPHER_CTX *in)
{
memcpy(out, in, sizeof(EVP_CIPHER_CTX));
-#if defined(HAVE_ENGINE_ADD) && defined(HAVE_EVP_CIPHER_CTX_ENGINE)
+#if !defined(OPENSSL_NO_ENGINE)
if (in->engine) ENGINE_add(out->engine);
if (in->cipher_data) {
out->cipher_data = OPENSSL_malloc(in->cipher->ctx_size);
@@ -133,222 +44,54 @@ EVP_CIPHER_CTX_copy(EVP_CIPHER_CTX *out, EVP_CIPHER_CTX *in)
}
#endif
-#if !defined(HAVE_X509_CRL_SET_VERSION)
-int
-X509_CRL_set_version(X509_CRL *x, long version)
-{
- if (x == NULL || x->crl == NULL) return 0;
- if (x->crl->version == NULL) {
- x->crl->version = M_ASN1_INTEGER_new();
- if (x->crl->version == NULL) return 0;
- }
- return ASN1_INTEGER_set(x->crl->version, version);
-}
-#endif
-
-#if !defined(HAVE_X509_CRL_SET_ISSUER_NAME)
-int
-X509_CRL_set_issuer_name(X509_CRL *x, X509_NAME *name)
-{
- if (x == NULL || x->crl == NULL) return 0;
- return X509_NAME_set(&x->crl->issuer, name);
-}
-#endif
-
-#if !defined(HAVE_X509_CRL_SORT)
-int
-X509_CRL_sort(X509_CRL *c)
-{
- int i;
- X509_REVOKED *r;
- /* sort the data so it will be written in serial
- * number order */
- sk_X509_REVOKED_sort(c->crl->revoked);
- for (i=0; i<sk_X509_REVOKED_num(c->crl->revoked); i++) {
- r=sk_X509_REVOKED_value(c->crl->revoked, i);
- r->sequence=i;
- }
- return 1;
-}
-#endif
-
-#if !defined(HAVE_X509_CRL_ADD0_REVOKED)
-static int
-OSSL_X509_REVOKED_cmp(const X509_REVOKED * const *a, const X509_REVOKED * const *b)
-{
- return(ASN1_STRING_cmp(
- (ASN1_STRING *)(*a)->serialNumber,
- (ASN1_STRING *)(*b)->serialNumber));
-}
-
-int
-X509_CRL_add0_revoked(X509_CRL *crl, X509_REVOKED *rev)
-{
- X509_CRL_INFO *inf;
-
- inf = crl->crl;
- if (!inf->revoked)
- inf->revoked = sk_X509_REVOKED_new(OSSL_X509_REVOKED_cmp);
- if (!inf->revoked || !sk_X509_REVOKED_push(inf->revoked, rev))
- return 0;
- return 1;
-}
-#endif
-
-#if !defined(HAVE_BN_MOD_SQR)
-int
-BN_mod_sqr(BIGNUM *r, const BIGNUM *a, const BIGNUM *m, BN_CTX *ctx)
-{
- if (!BN_sqr(r, (BIGNUM*)a, ctx)) return 0;
- return BN_mod(r, r, m, ctx);
-}
-#endif
-
-#if !defined(HAVE_BN_MOD_ADD) || !defined(HAVE_BN_MOD_SUB)
-int BN_nnmod(BIGNUM *r, const BIGNUM *m, const BIGNUM *d, BN_CTX *ctx)
-{
- if (!BN_mod(r,m,d,ctx)) return 0;
- if (!r->neg) return 1;
- return (d->neg ? BN_sub : BN_add)(r, r, d);
-}
-#endif
-
-#if !defined(HAVE_BN_MOD_ADD)
-int
-BN_mod_add(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, const BIGNUM *m, BN_CTX *ctx)
-{
- if (!BN_add(r, a, b)) return 0;
- return BN_nnmod(r, r, m, ctx);
-}
-#endif
-
-#if !defined(HAVE_BN_MOD_SUB)
-int
-BN_mod_sub(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, const BIGNUM *m, BN_CTX *ctx)
-{
- if (!BN_sub(r, a, b)) return 0;
- return BN_nnmod(r, r, m, ctx);
-}
-#endif
-
-#if !defined(HAVE_BN_RAND_RANGE) || !defined(HAVE_BN_PSEUDO_RAND_RANGE)
-static int
-bn_rand_range(int pseudo, BIGNUM *r, BIGNUM *range)
-{
- int (*bn_rand)(BIGNUM *, int, int, int) = pseudo ? BN_pseudo_rand : BN_rand;
- int n;
-
- if (range->neg || BN_is_zero(range)) return 0;
-
- n = BN_num_bits(range);
-
- if (n == 1) {
- if (!BN_zero(r)) return 0;
- } else if (!BN_is_bit_set(range, n - 2) && !BN_is_bit_set(range, n - 3)) {
- do {
- if (!bn_rand(r, n + 1, -1, 0)) return 0;
- if (BN_cmp(r ,range) >= 0) {
- if (!BN_sub(r, r, range)) return 0;
- if (BN_cmp(r, range) >= 0)
- if (!BN_sub(r, r, range)) return 0;
- }
- } while (BN_cmp(r, range) >= 0);
- } else {
- do {
- if (!bn_rand(r, n, -1, 0)) return 0;
- } while (BN_cmp(r, range) >= 0);
- }
-
- return 1;
-}
-#endif
-
-#if !defined(HAVE_BN_RAND_RANGE)
-int
-BN_rand_range(BIGNUM *r, BIGNUM *range)
+#if !defined(OPENSSL_NO_HMAC)
+#if !defined(HAVE_HMAC_CTX_COPY)
+void
+HMAC_CTX_copy(HMAC_CTX *out, HMAC_CTX *in)
{
- return bn_rand_range(0, r, range);
-}
-#endif
+ if (!out || !in) return;
+ memcpy(out, in, sizeof(HMAC_CTX));
-#if !defined(HAVE_BN_PSEUDO_RAND_RANGE)
-int
-BN_pseudo_rand_range(BIGNUM *r, BIGNUM *range)
-{
- return bn_rand_range(1, r, range);
+ EVP_MD_CTX_copy(&out->md_ctx, &in->md_ctx);
+ EVP_MD_CTX_copy(&out->i_ctx, &in->i_ctx);
+ EVP_MD_CTX_copy(&out->o_ctx, &in->o_ctx);
}
-#endif
-
-#if !defined(HAVE_CONF_GET1_DEFAULT_CONFIG_FILE)
-#define OPENSSL_CONF "openssl.cnf"
-char *
-CONF_get1_default_config_file(void)
-{
- char *file;
- int len;
-
- file = getenv("OPENSSL_CONF");
- if (file) return BUF_strdup(file);
- len = strlen(X509_get_default_cert_area());
-#ifndef OPENSSL_SYS_VMS
- len++;
-#endif
- len += strlen(OPENSSL_CONF);
- file = OPENSSL_malloc(len + 1);
- if (!file) return NULL;
- strcpy(file,X509_get_default_cert_area());
-#ifndef OPENSSL_SYS_VMS
- strcat(file,"/");
-#endif
- strcat(file,OPENSSL_CONF);
+#endif /* HAVE_HMAC_CTX_COPY */
+#endif /* NO_HMAC */
- return file;
-}
-#endif
+/* added in 1.0.2 */
+#if !defined(OPENSSL_NO_EC)
+#if !defined(HAVE_EC_CURVE_NIST2NID)
+static struct {
+ const char *name;
+ int nid;
+} nist_curves[] = {
+ {"B-163", NID_sect163r2},
+ {"B-233", NID_sect233r1},
+ {"B-283", NID_sect283r1},
+ {"B-409", NID_sect409r1},
+ {"B-571", NID_sect571r1},
+ {"K-163", NID_sect163k1},
+ {"K-233", NID_sect233k1},
+ {"K-283", NID_sect283k1},
+ {"K-409", NID_sect409k1},
+ {"K-571", NID_sect571k1},
+ {"P-192", NID_X9_62_prime192v1},
+ {"P-224", NID_secp224r1},
+ {"P-256", NID_X9_62_prime256v1},
+ {"P-384", NID_secp384r1},
+ {"P-521", NID_secp521r1}
+};
-#if !defined(HAVE_PEM_DEF_CALLBACK)
-#define OSSL_PASS_MIN_LENGTH 4
int
-PEM_def_callback(char *buf, int num, int w, void *key)
+EC_curve_nist2nid(const char *name)
{
- int i,j;
- const char *prompt;
-
- if (key) {
- i = strlen(key);
- i = (i > num) ? num : i;
- memcpy(buf, key, i);
- return i;
- }
-
- prompt = EVP_get_pw_prompt();
- if (prompt == NULL) prompt = "Enter PEM pass phrase:";
- for (;;) {
- i = EVP_read_pw_string(buf, num, prompt, w);
- if (i != 0) {
- memset(buf, 0, (unsigned int)num);
- return(-1);
- }
- j = strlen(buf);
- if (j < OSSL_PASS_MIN_LENGTH) {
- fprintf(stderr,
- "phrase is too short, needs to be at least %d chars\n",
- OSSL_PASS_MIN_LENGTH);
- }
- else break;
+ size_t i;
+ for (i = 0; i < (sizeof(nist_curves) / sizeof(nist_curves[0])); i++) {
+ if (!strcmp(nist_curves[i].name, name))
+ return nist_curves[i].nid;
}
- return j;
+ return NID_undef;
}
#endif
-
-#if !defined(HAVE_ASN1_PUT_EOC)
-int
-ASN1_put_eoc(unsigned char **pp)
-{
- unsigned char *p = *pp;
- *p++ = 0;
- *p++ = 0;
- *pp = p;
- return 2;
-}
#endif
diff --git a/ext/openssl/openssl_missing.h b/ext/openssl/openssl_missing.h
index 2dc49d3f..b8f9d3d1 100644
--- a/ext/openssl/openssl_missing.h
+++ b/ext/openssl/openssl_missing.h
@@ -10,187 +10,39 @@
#if !defined(_OSSL_OPENSSL_MISSING_H_)
#define _OSSL_OPENSSL_MISSING_H_
-#if defined(__cplusplus)
-extern "C" {
-#endif
-
-#ifndef TYPEDEF_D2I_OF
-typedef char *d2i_of_void();
-#endif
-#ifndef TYPEDEF_I2D_OF
-typedef int i2d_of_void();
-#endif
-
-/*
- * These functions are not included in headers of OPENSSL <= 0.9.6b
- */
-
-#if !defined(PEM_read_bio_DSAPublicKey)
-# define PEM_read_bio_DSAPublicKey(bp,x,cb,u) (DSA *)PEM_ASN1_read_bio( \
- (d2i_of_void *)d2i_DSAPublicKey,PEM_STRING_DSA_PUBLIC,(bp),(void **)(x),(cb),(u))
-#endif
-
-#if !defined(PEM_write_bio_DSAPublicKey)
-# define PEM_write_bio_DSAPublicKey(bp,x) \
- PEM_ASN1_write_bio((i2d_of_void *)i2d_DSAPublicKey,\
- PEM_STRING_DSA_PUBLIC,\
- (bp),(char *)(x), NULL, NULL, 0, NULL, NULL)
-#endif
-
-#if !defined(DSAPrivateKey_dup)
-# define DSAPrivateKey_dup(dsa) (DSA *)ASN1_dup((i2d_of_void *)i2d_DSAPrivateKey, \
- (d2i_of_void *)d2i_DSAPrivateKey,(char *)(dsa))
-#endif
-
-#if !defined(DSAPublicKey_dup)
-# define DSAPublicKey_dup(dsa) (DSA *)ASN1_dup((i2d_of_void *)i2d_DSAPublicKey, \
- (d2i_of_void *)d2i_DSAPublicKey,(char *)(dsa))
-#endif
-
-#if !defined(X509_REVOKED_dup)
-# define X509_REVOKED_dup(rev) (X509_REVOKED *)ASN1_dup((i2d_of_void *)i2d_X509_REVOKED, \
- (d2i_of_void *)d2i_X509_REVOKED, (char *)(rev))
-#endif
-
-#if !defined(PKCS7_SIGNER_INFO_dup)
-# define PKCS7_SIGNER_INFO_dup(si) (PKCS7_SIGNER_INFO *)ASN1_dup((i2d_of_void *)i2d_PKCS7_SIGNER_INFO, \
- (d2i_of_void *)d2i_PKCS7_SIGNER_INFO, (char *)(si))
-#endif
-
-#if !defined(PKCS7_RECIP_INFO_dup)
-# define PKCS7_RECIP_INFO_dup(ri) (PKCS7_RECIP_INFO *)ASN1_dup((i2d_of_void *)i2d_PKCS7_RECIP_INFO, \
- (d2i_of_void *)d2i_PKCS7_RECIP_INFO, (char *)(ri))
-#endif
-
-#if !defined(HAVE_HMAC_CTX_INIT)
-void HMAC_CTX_init(HMAC_CTX *ctx);
+/* added in 1.0.0 */
+#if !defined(HAVE_EVP_CIPHER_CTX_COPY)
+int EVP_CIPHER_CTX_copy(EVP_CIPHER_CTX *out, const EVP_CIPHER_CTX *in);
#endif
#if !defined(HAVE_HMAC_CTX_COPY)
void HMAC_CTX_copy(HMAC_CTX *out, HMAC_CTX *in);
#endif
-#if !defined(HAVE_HMAC_CTX_CLEANUP)
-void HMAC_CTX_cleanup(HMAC_CTX *ctx);
-#endif
-
-#if !defined(HAVE_EVP_MD_CTX_CREATE)
-EVP_MD_CTX *EVP_MD_CTX_create(void);
-#endif
-
-#if !defined(HAVE_EVP_MD_CTX_INIT)
-void EVP_MD_CTX_init(EVP_MD_CTX *ctx);
-#endif
-
-#if !defined(HAVE_EVP_MD_CTX_CLEANUP)
-int EVP_MD_CTX_cleanup(EVP_MD_CTX *ctx);
-#endif
-
-#if !defined(HAVE_EVP_MD_CTX_DESTROY)
-void EVP_MD_CTX_destroy(EVP_MD_CTX *ctx);
-#endif
-
-#if !defined(HAVE_EVP_CIPHER_CTX_COPY)
-int EVP_CIPHER_CTX_copy(EVP_CIPHER_CTX *out, EVP_CIPHER_CTX *in);
-#endif
-
-#if !defined(HAVE_EVP_DIGESTINIT_EX)
-# define EVP_DigestInit_ex(ctx, md, engine) EVP_DigestInit((ctx), (md))
-#endif
-#if !defined(HAVE_EVP_DIGESTFINAL_EX)
-# define EVP_DigestFinal_ex(ctx, buf, len) EVP_DigestFinal((ctx), (buf), (len))
-#endif
-
-#if !defined(HAVE_EVP_CIPHERINIT_EX)
-# define EVP_CipherInit_ex(ctx, type, impl, key, iv, enc) EVP_CipherInit((ctx), (type), (key), (iv), (enc))
-#endif
-#if !defined(HAVE_EVP_CIPHERFINAL_EX)
-# define EVP_CipherFinal_ex(ctx, outm, outl) EVP_CipherFinal((ctx), (outm), (outl))
-#endif
-
-#if !defined(EVP_CIPHER_name)
-# define EVP_CIPHER_name(e) OBJ_nid2sn(EVP_CIPHER_nid(e))
-#endif
-
-#if !defined(EVP_MD_name)
-# define EVP_MD_name(e) OBJ_nid2sn(EVP_MD_type(e))
-#endif
-
-#if !defined(HAVE_EVP_HMAC_INIT_EX)
-# define HMAC_Init_ex(ctx, key, len, digest, engine) HMAC_Init((ctx), (key), (len), (digest))
-#endif
-
-#if !defined(PKCS7_is_detached)
-# define PKCS7_is_detached(p7) (PKCS7_type_is_signed(p7) && PKCS7_get_detached(p7))
+/* added in 1.0.2 */
+#if !defined(OPENSSL_NO_EC)
+#if !defined(HAVE_EC_CURVE_NIST2NID)
+int EC_curve_nist2nid(const char *);
#endif
-
-#if !defined(PKCS7_type_is_encrypted)
-# define PKCS7_type_is_encrypted(a) (OBJ_obj2nid((a)->type) == NID_pkcs7_encrypted)
#endif
-#if !defined(HAVE_OPENSSL_CLEANSE)
-#define OPENSSL_cleanse(p, l) memset((p), 0, (l))
+#if !defined(HAVE_X509_REVOKED_DUP)
+# define X509_REVOKED_dup(rev) (X509_REVOKED *)ASN1_dup((i2d_of_void *)i2d_X509_REVOKED, \
+ (d2i_of_void *)d2i_X509_REVOKED, (char *)(rev))
#endif
+/* added in 1.1.0 */
#if !defined(HAVE_X509_STORE_GET_EX_DATA)
-void *X509_STORE_get_ex_data(X509_STORE *str, int idx);
+# define X509_STORE_get_ex_data(x, idx) \
+ CRYPTO_get_ex_data(&(x)->ex_data, (idx))
#endif
#if !defined(HAVE_X509_STORE_SET_EX_DATA)
-int X509_STORE_set_ex_data(X509_STORE *str, int idx, void *data);
-#endif
-
-#if !defined(HAVE_X509_CRL_SET_VERSION)
-int X509_CRL_set_version(X509_CRL *x, long version);
-#endif
-
-#if !defined(HAVE_X509_CRL_SET_ISSUER_NAME)
-int X509_CRL_set_issuer_name(X509_CRL *x, X509_NAME *name);
-#endif
-
-#if !defined(HAVE_X509_CRL_SORT)
-int X509_CRL_sort(X509_CRL *c);
-#endif
-
-#if !defined(HAVE_X509_CRL_ADD0_REVOKED)
-int X509_CRL_add0_revoked(X509_CRL *crl, X509_REVOKED *rev);
-#endif
-
-#if !defined(HAVE_BN_MOD_SQR)
-int BN_mod_sqr(BIGNUM *r, const BIGNUM *a, const BIGNUM *m, BN_CTX *ctx);
-#endif
-
-#if !defined(HAVE_BN_MOD_ADD)
-int BN_mod_add(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, const BIGNUM *m, BN_CTX *ctx);
-#endif
-
-#if !defined(HAVE_BN_MOD_SUB)
-int BN_mod_sub(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, const BIGNUM *m, BN_CTX *ctx);
-#endif
-
-#if !defined(HAVE_BN_RAND_RANGE)
-int BN_rand_range(BIGNUM *r, BIGNUM *range);
-#endif
-
-#if !defined(HAVE_BN_PSEUDO_RAND_RANGE)
-int BN_pseudo_rand_range(BIGNUM *r, BIGNUM *range);
-#endif
-
-#if !defined(HAVE_CONF_GET1_DEFAULT_CONFIG_FILE)
-char *CONF_get1_default_config_file(void);
-#endif
-
-#if !defined(HAVE_PEM_DEF_CALLBACK)
-int PEM_def_callback(char *buf, int num, int w, void *key);
+# define X509_STORE_set_ex_data(x, idx, data) \
+ CRYPTO_set_ex_data(&(x)->ex_data, (idx), (data))
+# define X509_STORE_get_ex_new_index(l, p, newf, dupf, freef) \
+ CRYPTO_get_ex_new_index(CRYPTO_EX_INDEX_X509_STORE, (l), (p), \
+ (newf), (dupf), (freef))
#endif
-#if !defined(HAVE_ASN1_PUT_EOC)
-int ASN1_put_eoc(unsigned char **pp);
-#endif
-
-#if defined(__cplusplus)
-}
-#endif
-
-
#endif /* _OSSL_OPENSSL_MISSING_H_ */
diff --git a/ext/openssl/ossl.c b/ext/openssl/ossl.c
index d03dfa7a..3654b1e8 100644
--- a/ext/openssl/ossl.c
+++ b/ext/openssl/ossl.c
@@ -147,6 +147,31 @@ ossl_buf2str(char *buf, int len)
/*
* our default PEM callback
*/
+
+/*
+ * OpenSSL requires passwords for PEM-encoded files to be at least four
+ * characters long. See crypto/pem/pem_lib.c (as of 1.0.2h)
+ */
+#define OSSL_MIN_PWD_LEN 4
+
+VALUE
+ossl_pem_passwd_value(VALUE pass)
+{
+ if (NIL_P(pass))
+ return Qnil;
+
+ StringValue(pass);
+
+ if (RSTRING_LEN(pass) < OSSL_MIN_PWD_LEN)
+ ossl_raise(eOSSLError, "password must be at least %d bytes", OSSL_MIN_PWD_LEN);
+ /* 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);
+
+ return pass;
+}
+
static VALUE
ossl_pem_passwd_cb0(VALUE flag)
{
@@ -159,13 +184,29 @@ ossl_pem_passwd_cb0(VALUE flag)
}
int
-ossl_pem_passwd_cb(char *buf, int max_len, int flag, void *pwd)
+ossl_pem_passwd_cb(char *buf, int max_len, int flag, void *pwd_)
{
- int len, status = 0;
- VALUE rflag, pass;
+ int len, status;
+ VALUE rflag, pass = (VALUE)pwd_;
+
+ if (RTEST(pass)) {
+ /* PEM_def_callback(buf, max_len, flag, StringValueCStr(pass)) does not
+ * 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);
+ if (len >= OSSL_MIN_PWD_LEN && len <= max_len) {
+ memcpy(buf, RSTRING_PTR(pass), len);
+ return len;
+ }
+ }
+ OSSL_Debug("passed data is not valid String???");
+ return -1;
+ }
- if (pwd || !rb_block_given_p())
- return PEM_def_callback(buf, max_len, flag, pwd);
+ if (!rb_block_given_p()) {
+ return PEM_def_callback(buf, max_len, flag, NULL);
+ }
while (1) {
/*
@@ -181,12 +222,12 @@ ossl_pem_passwd_cb(char *buf, int max_len, int flag, void *pwd)
return -1;
}
len = RSTRING_LENINT(pass);
- if (len < 4) { /* 4 is OpenSSL hardcoded limit */
- rb_warning("password must be longer than 4 bytes");
+ 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 then %d bytes", max_len-1);
+ rb_warning("password must be shorter than %d bytes", max_len);
continue;
}
memcpy(buf, RSTRING_PTR(pass), len);
@@ -198,7 +239,8 @@ ossl_pem_passwd_cb(char *buf, int max_len, int flag, void *pwd)
/*
* Verify callback
*/
-int ossl_verify_cb_idx;
+int ossl_store_ctx_ex_verify_cb_idx;
+int ossl_store_ex_verify_cb_idx;
VALUE
ossl_call_verify_cb_proc(struct ossl_verify_cb_args *args)
@@ -214,10 +256,10 @@ ossl_verify_cb(int ok, X509_STORE_CTX *ctx)
struct ossl_verify_cb_args args;
int state = 0;
- proc = (VALUE)X509_STORE_CTX_get_ex_data(ctx, ossl_verify_cb_idx);
- if ((void*)proc == 0)
- proc = (VALUE)X509_STORE_get_ex_data(ctx->ctx, ossl_verify_cb_idx);
- if ((void*)proc == 0)
+ proc = (VALUE)X509_STORE_CTX_get_ex_data(ctx, ossl_store_ctx_ex_verify_cb_idx);
+ if (!proc)
+ proc = (VALUE)X509_STORE_get_ex_data(ctx->ctx, ossl_store_ex_verify_cb_idx);
+ if (!proc)
return ok;
if (!NIL_P(proc)) {
ret = Qfalse;
@@ -297,11 +339,7 @@ ossl_make_error(VALUE exc, const char *fmt, va_list args)
const char *msg;
long e;
-#ifdef HAVE_ERR_PEEK_LAST_ERROR
e = ERR_peek_last_error();
-#else
- e = ERR_peek_error();
-#endif
if (fmt) {
str = rb_vsprintf(fmt, args);
}
@@ -318,12 +356,7 @@ ossl_make_error(VALUE exc, const char *fmt, va_list args)
rb_str_cat2(str, msg ? msg : "(null)");
}
}
- if (dOSSL == Qtrue){ /* show all errors on the stack */
- while ((e = ERR_get_error()) != 0){
- rb_warn("error on stack: %s", ERR_error_string(e, NULL));
- }
- }
- ERR_clear_error();
+ ossl_clear_error();
if (NIL_P(str)) str = rb_str_new(0, 0);
return rb_exc_new3(exc, str);
@@ -351,6 +384,18 @@ ossl_exc_new(VALUE exc, const char *fmt, ...)
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));
+ }
+ }
+ ERR_clear_error();
+}
+
/*
* call-seq:
* OpenSSL.errors -> [String...]
@@ -446,7 +491,7 @@ static VALUE
ossl_fips_mode_set(VALUE self, VALUE enabled)
{
-#ifdef HAVE_OPENSSL_FIPS
+#ifdef OPENSSL_FIPS
if (RTEST(enabled)) {
int mode = FIPS_mode();
if(!mode && !FIPS_mode_set(1)) /* turning on twice leads to an error */
@@ -1018,8 +1063,8 @@ static void Init_ossl_locks(void)
*
* require 'socket'
*
- * tcp_client = TCPSocket.new 'localhost', 5000
- * ssl_client = OpenSSL::SSL::SSLSocket.new client_socket, context
+ * tcp_socket = TCPSocket.new 'localhost', 5000
+ * ssl_client = OpenSSL::SSL::SSLSocket.new tcp_socket, context
* ssl_client.connect
*
* ssl_client.puts "hello server!"
@@ -1038,8 +1083,8 @@ static void Init_ossl_locks(void)
*
* require 'socket'
*
- * tcp_client = TCPSocket.new 'localhost', 5000
- * ssl_client = OpenSSL::SSL::SSLSocket.new client_socket, context
+ * tcp_socket = TCPSocket.new 'localhost', 5000
+ * ssl_client = OpenSSL::SSL::SSLSocket.new tcp_socket, context
* ssl_client.connect
*
* ssl_client.puts "hello server!"
@@ -1113,7 +1158,7 @@ Init_openssl(void)
/*
* Boolean indicating whether OpenSSL is FIPS-enabled or not
*/
-#ifdef HAVE_OPENSSL_FIPS
+#ifdef OPENSSL_FIPS
rb_define_const(mOSSL, "OPENSSL_FIPS", Qtrue);
#else
rb_define_const(mOSSL, "OPENSSL_FIPS", Qfalse);
@@ -1128,12 +1173,6 @@ Init_openssl(void)
rb_global_variable(&eOSSLError);
/*
- * Verify callback Proc index for ext-data
- */
- if ((ossl_verify_cb_idx = X509_STORE_CTX_get_ex_new_index(0, (void *)"ossl_verify_cb_idx", 0, 0, 0)) < 0)
- ossl_raise(eOSSLError, "X509_STORE_CTX_get_ex_new_index");
-
- /*
* Init debug core
*/
dOSSL = Qfalse;
@@ -1144,6 +1183,14 @@ 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 3be01b0c..2317fa8b 100644
--- a/ext/openssl/ossl.h
+++ b/ext/openssl/ossl.h
@@ -12,10 +12,6 @@
#include RUBY_EXTCONF_H
-#if defined(__cplusplus)
-extern "C" {
-#endif
-
#if 0
mOSSL = rb_define_module("OpenSSL");
mX509 = rb_define_module_under(mOSSL, "X509");
@@ -31,11 +27,6 @@ extern "C" {
#include <ruby/io.h>
#include <ruby/thread.h>
-/*
- * Check the OpenSSL version
- * The only supported are:
- * OpenSSL >= 0.9.7
- */
#include <openssl/opensslv.h>
#ifdef HAVE_ASSERT_H
@@ -46,7 +37,6 @@ extern "C" {
#if defined(_WIN32) && !defined(LIBRESSL_VERSION_NUMBER)
# include <openssl/e_os2.h>
-# define OSSL_NO_CONF_API 1
# if !defined(OPENSSL_SYS_WIN32)
# define OPENSSL_SYS_WIN32 1
# endif
@@ -54,7 +44,7 @@ extern "C" {
#endif
#include <errno.h>
#include <openssl/err.h>
-#include <openssl/asn1_mac.h>
+#include <openssl/asn1.h>
#include <openssl/x509v3.h>
#include <openssl/ssl.h>
#include <openssl/pkcs12.h>
@@ -66,22 +56,13 @@ extern "C" {
#if !defined(_WIN32)
# include <openssl/crypto.h>
#endif
-#undef X509_NAME
-#undef PKCS7_SIGNER_INFO
-#if defined(HAVE_OPENSSL_ENGINE_H) && defined(HAVE_EVP_CIPHER_CTX_ENGINE)
-# define OSSL_ENGINE_ENABLED
+#if !defined(OPENSSL_NO_ENGINE)
# include <openssl/engine.h>
#endif
-#if defined(HAVE_OPENSSL_OCSP_H)
-# define OSSL_OCSP_ENABLED
+#if !defined(OPENSSL_NO_OCSP)
# include <openssl/ocsp.h>
#endif
-/* OpenSSL requires passwords for PEM-encoded files to be at least four
- * characters long
- */
-#define OSSL_MIN_PWD_LEN 4
-
/*
* Common Module
*/
@@ -116,13 +97,6 @@ extern VALUE eOSSLError;
} while (0)
/*
- * Compatibility
- */
-#if OPENSSL_VERSION_NUMBER >= 0x10000000L
-#define STACK _STACK
-#endif
-
-/*
* String to HEXString conversion
*/
int string2hex(const unsigned char *, int, char **, int *);
@@ -146,16 +120,24 @@ do{\
}while(0)
/*
- * our default PEM callback
+ * Our default PEM callback
*/
+/* Convert the argument to String and validate the length. Note this may raise. */
+VALUE ossl_pem_passwd_value(VALUE);
+/* Can be casted to pem_password_cb. If a password (String) is passed as the
+ * "arbitrary data" (typically the last parameter of PEM_{read,write}_
+ * functions), uses the value. If not, but a block is given, yields to it.
+ * If not either, fallbacks to PEM_def_callback() which reads from stdin. */
int ossl_pem_passwd_cb(char *, int, int, void *);
/*
* Clear BIO* with this in PEM/DER fallback scenarios to avoid decoding
* errors piling up in OpenSSL::Errors
*/
-#define OSSL_BIO_reset(bio) (void)BIO_reset((bio)); \
- ERR_clear_error();
+#define OSSL_BIO_reset(bio) do { \
+ (void)BIO_reset((bio)); \
+ ossl_clear_error(); \
+} while (0)
/*
* ERRor messages
@@ -163,11 +145,14 @@ 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_verify_cb_idx;
+extern int ossl_store_ctx_ex_verify_cb_idx;
+extern int ossl_store_ex_verify_cb_idx;
struct ossl_verify_cb_args {
VALUE proc;
@@ -241,8 +226,4 @@ void ossl_debug(const char *, ...);
void Init_openssl(void);
-#if defined(__cplusplus)
-}
-#endif
-
#endif /* _OSSL_H_ */
diff --git a/ext/openssl/ossl_asn1.c b/ext/openssl/ossl_asn1.c
index 89da5949..43a3d2d8 100644
--- a/ext/openssl/ossl_asn1.c
+++ b/ext/openssl/ossl_asn1.c
@@ -75,15 +75,10 @@ asn1time_to_time(ASN1_TIME *time)
return rb_funcall2(rb_cTime, rb_intern("utc"), 6, argv);
}
-/*
- * This function is not exported in Ruby's *.h
- */
-extern struct timeval rb_time_timeval(VALUE);
-
time_t
time_to_time_t(VALUE time)
{
- return (time_t)NUM2LONG(rb_Integer(time));
+ return (time_t)NUM2TIMET(rb_Integer(time));
}
/*
@@ -140,7 +135,7 @@ num_to_asn1integer(VALUE obj, ASN1_INTEGER *ai)
bn = GetBNPtr(obj);
} else {
obj = rb_String(obj);
- if (!BN_dec2bn(&bn, StringValuePtr(obj))) {
+ if (!BN_dec2bn(&bn, StringValueCStr(obj))) {
ossl_raise(eOSSLError, NULL);
}
}
@@ -212,19 +207,6 @@ static ID sUNIVERSAL, sAPPLICATION, sCONTEXT_SPECIFIC, sPRIVATE;
static ID sivVALUE, sivTAG, sivTAG_CLASS, sivTAGGING, sivINFINITE_LENGTH, sivUNUSED_BITS;
/*
- * We need to implement these for backward compatibility
- * reasons, behavior of ASN1_put_object and ASN1_object_size
- * for infinite length values is different in OpenSSL <= 0.9.7
- */
-#if OPENSSL_VERSION_NUMBER < 0x00908000L
-#define ossl_asn1_object_size(cons, len, tag) (cons) == 2 ? (len) + ASN1_object_size((cons), 0, (tag)) : ASN1_object_size((cons), (len), (tag))
-#define ossl_asn1_put_object(pp, cons, len, tag, xc) (cons) == 2 ? ASN1_put_object((pp), (cons), 0, (tag), (xc)) : ASN1_put_object((pp), (cons), (len), (tag), (xc))
-#else
-#define ossl_asn1_object_size(cons, len, tag) ASN1_object_size((cons), (len), (tag))
-#define ossl_asn1_put_object(pp, cons, len, tag, xc) ASN1_put_object((pp), (cons), (len), (tag), (xc))
-#endif
-
-/*
* Ruby to ASN1 converters
*/
static ASN1_BOOLEAN
@@ -233,11 +215,7 @@ obj_to_asn1bool(VALUE obj)
if (NIL_P(obj))
ossl_raise(rb_eTypeError, "Can't convert nil into Boolean");
-#if OPENSSL_VERSION_NUMBER < 0x00907000L
- return RTEST(obj) ? 0xff : 0x100;
-#else
return RTEST(obj) ? 0xff : 0x0;
-#endif
}
static ASN1_INTEGER*
@@ -293,10 +271,10 @@ obj_to_asn1obj(VALUE obj)
{
ASN1_OBJECT *a1obj;
- StringValue(obj);
+ StringValueCStr(obj);
a1obj = OBJ_txt2obj(RSTRING_PTR(obj), 0);
if(!a1obj) a1obj = OBJ_txt2obj(RSTRING_PTR(obj), 1);
- if(!a1obj) ossl_raise(eASN1Error, "invalid OBJECT ID");
+ if(!a1obj) ossl_raise(eASN1Error, "invalid OBJECT ID %"PRIsVALUE, obj);
return a1obj;
}
@@ -778,11 +756,11 @@ ossl_asn1data_to_der(VALUE self)
if (inf_length == Qtrue) {
is_cons = 2;
}
- if((length = ossl_asn1_object_size(is_cons, RSTRING_LENINT(value), tag)) <= 0)
+ if((length = ASN1_object_size(is_cons, RSTRING_LENINT(value), tag)) <= 0)
ossl_raise(eASN1Error, NULL);
der = rb_str_new(0, length);
p = (unsigned char *)RSTRING_PTR(der);
- ossl_asn1_put_object(&p, is_cons, RSTRING_LENINT(value), tag, tag_class);
+ ASN1_put_object(&p, is_cons, RSTRING_LENINT(value), tag, tag_class);
memcpy(p, RSTRING_PTR(value), RSTRING_LEN(value));
p += RSTRING_LEN(value);
ossl_str_adjust(der, p);
@@ -1184,30 +1162,6 @@ ossl_asn1eoc_initialize(VALUE self) {
return self;
}
-static int
-ossl_i2d_ASN1_TYPE(ASN1_TYPE *a, unsigned char **pp)
-{
-#if OPENSSL_VERSION_NUMBER < 0x00907000L
- if(!a) return 0;
- if(a->type == V_ASN1_BOOLEAN)
- return i2d_ASN1_BOOLEAN(a->value.boolean, pp);
-#endif
- return i2d_ASN1_TYPE(a, pp);
-}
-
-static void
-ossl_ASN1_TYPE_free(ASN1_TYPE *a)
-{
-#if OPENSSL_VERSION_NUMBER < 0x00907000L
- if(!a) return;
- if(a->type == V_ASN1_BOOLEAN){
- OPENSSL_free(a);
- return;
- }
-#endif
- ASN1_TYPE_free(a);
-}
-
/*
* call-seq:
* asn1.to_der => DER-encoded String
@@ -1228,22 +1182,22 @@ ossl_asn1prim_to_der(VALUE self)
explicit = ossl_asn1_is_explicit(self);
asn1 = ossl_asn1_get_asn1type(self);
- len = ossl_asn1_object_size(1, ossl_i2d_ASN1_TYPE(asn1, NULL), tn);
+ len = ASN1_object_size(1, i2d_ASN1_TYPE(asn1, NULL), tn);
if(!(buf = OPENSSL_malloc(len))){
- ossl_ASN1_TYPE_free(asn1);
+ ASN1_TYPE_free(asn1);
ossl_raise(eASN1Error, "cannot alloc buffer");
}
p = buf;
if (tc == V_ASN1_UNIVERSAL) {
- ossl_i2d_ASN1_TYPE(asn1, &p);
+ i2d_ASN1_TYPE(asn1, &p);
} else if (explicit) {
- ossl_asn1_put_object(&p, 1, ossl_i2d_ASN1_TYPE(asn1, NULL), tn, tc);
- ossl_i2d_ASN1_TYPE(asn1, &p);
+ ASN1_put_object(&p, 1, i2d_ASN1_TYPE(asn1, NULL), tn, tc);
+ i2d_ASN1_TYPE(asn1, &p);
} else {
- ossl_i2d_ASN1_TYPE(asn1, &p);
+ i2d_ASN1_TYPE(asn1, &p);
*buf = tc | tn | (*buf & V_ASN1_CONSTRUCTED);
}
- ossl_ASN1_TYPE_free(asn1);
+ ASN1_TYPE_free(asn1);
reallen = p - buf;
assert(reallen <= len);
str = ossl_buf2str((char *)buf, rb_long2int(reallen)); /* buf will be free in ossl_buf2str */
@@ -1309,19 +1263,19 @@ ossl_asn1cons_to_der(VALUE self)
explicit = ossl_asn1_is_explicit(self);
value = join_der(ossl_asn1_get_value(self));
- seq_len = ossl_asn1_object_size(constructed, RSTRING_LENINT(value), tag);
- length = ossl_asn1_object_size(constructed, seq_len, tn);
+ seq_len = ASN1_object_size(constructed, RSTRING_LENINT(value), tag);
+ length = ASN1_object_size(constructed, seq_len, tn);
str = rb_str_new(0, length);
p = (unsigned char *)RSTRING_PTR(str);
if(tc == V_ASN1_UNIVERSAL)
- ossl_asn1_put_object(&p, constructed, RSTRING_LENINT(value), tn, tc);
+ ASN1_put_object(&p, constructed, RSTRING_LENINT(value), tn, tc);
else{
if(explicit){
- ossl_asn1_put_object(&p, constructed, seq_len, tn, tc);
- ossl_asn1_put_object(&p, constructed, RSTRING_LENINT(value), tag, V_ASN1_UNIVERSAL);
+ ASN1_put_object(&p, constructed, seq_len, tn, tc);
+ ASN1_put_object(&p, constructed, RSTRING_LENINT(value), tag, V_ASN1_UNIVERSAL);
}
else{
- ossl_asn1_put_object(&p, constructed, RSTRING_LENINT(value), tn, tc);
+ ASN1_put_object(&p, constructed, RSTRING_LENINT(value), tn, tc);
}
}
memcpy(p, RSTRING_PTR(value), RSTRING_LEN(value));
@@ -1374,9 +1328,9 @@ ossl_asn1cons_each(VALUE self)
static VALUE
ossl_asn1obj_s_register(VALUE self, VALUE oid, VALUE sn, VALUE ln)
{
- StringValue(oid);
- StringValue(sn);
- StringValue(ln);
+ StringValueCStr(oid);
+ StringValueCStr(sn);
+ StringValueCStr(ln);
if(!OBJ_create(RSTRING_PTR(oid), RSTRING_PTR(sn), RSTRING_PTR(ln)))
ossl_raise(eASN1Error, NULL);
@@ -1399,7 +1353,7 @@ ossl_asn1obj_get_sn(VALUE self)
int nid;
val = ossl_asn1_get_value(self);
- if ((nid = OBJ_txt2nid(StringValuePtr(val))) != NID_undef)
+ if ((nid = OBJ_txt2nid(StringValueCStr(val))) != NID_undef)
ret = rb_str_new2(OBJ_nid2sn(nid));
return ret;
@@ -1420,7 +1374,7 @@ ossl_asn1obj_get_ln(VALUE self)
int nid;
val = ossl_asn1_get_value(self);
- if ((nid = OBJ_txt2nid(StringValuePtr(val))) != NID_undef)
+ if ((nid = OBJ_txt2nid(StringValueCStr(val))) != NID_undef)
ret = rb_str_new2(OBJ_nid2ln(nid));
return ret;
diff --git a/ext/openssl/ossl_bn.c b/ext/openssl/ossl_bn.c
index fba86cdd..5b4207ba 100644
--- a/ext/openssl/ossl_bn.c
+++ b/ext/openssl/ossl_bn.c
@@ -82,8 +82,8 @@ ossl_bn_new(const BIGNUM *bn)
return obj;
}
-BIGNUM *
-GetBNPtr(VALUE obj)
+static BIGNUM *
+try_convert_to_bnptr(VALUE obj)
{
BIGNUM *bn = NULL;
VALUE newobj;
@@ -95,19 +95,25 @@ GetBNPtr(VALUE obj)
case T_BIGNUM:
obj = rb_String(obj);
newobj = NewBN(cBN); /* GC bug */
- if (!BN_dec2bn(&bn, StringValuePtr(obj))) {
+ if (!BN_dec2bn(&bn, StringValueCStr(obj))) {
ossl_raise(eBNError, NULL);
}
SetBN(newobj, bn); /* Handle potencial mem leaks */
break;
- case T_NIL:
- break;
- default:
- ossl_raise(rb_eTypeError, "Cannot convert into OpenSSL::BN");
}
return bn;
}
+BIGNUM *
+GetBNPtr(VALUE obj)
+{
+ BIGNUM *bn = try_convert_to_bnptr(obj);
+ if (!bn)
+ ossl_raise(rb_eTypeError, "Cannot convert into OpenSSL::BN");
+
+ return bn;
+}
+
/*
* Private
*/
@@ -203,26 +209,25 @@ ossl_bn_initialize(int argc, VALUE *argv, VALUE self)
return self;
}
- StringValue(str);
GetBN(self, bn);
switch (base) {
case 0:
- if (!BN_mpi2bn((unsigned char *)RSTRING_PTR(str), RSTRING_LENINT(str), bn)) {
+ if (!BN_mpi2bn((unsigned char *)StringValuePtr(str), RSTRING_LENINT(str), bn)) {
ossl_raise(eBNError, NULL);
}
break;
case 2:
- if (!BN_bin2bn((unsigned char *)RSTRING_PTR(str), RSTRING_LENINT(str), bn)) {
+ if (!BN_bin2bn((unsigned char *)StringValuePtr(str), RSTRING_LENINT(str), bn)) {
ossl_raise(eBNError, NULL);
}
break;
case 10:
- if (!BN_dec2bn(&bn, RSTRING_PTR(str))) {
+ if (!BN_dec2bn(&bn, StringValueCStr(str))) {
ossl_raise(eBNError, NULL);
}
break;
case 16:
- if (!BN_hex2bn(&bn, RSTRING_PTR(str))) {
+ if (!BN_hex2bn(&bn, StringValueCStr(str))) {
ossl_raise(eBNError, NULL);
}
break;
@@ -841,21 +846,78 @@ BIGNUM_CMP(ucmp)
/*
* call-seq:
- * big.eql?(obj) => true or false
+ * bn == obj => true or false
*
- * Returns <code>true</code> only if <i>obj</i> is a
- * <code>Bignum</code> with the same value as <i>big</i>. Contrast this
+ * Returns +true+ only if +obj+ has the same value as +bn+. Contrast this
+ * with OpenSSL::BN#eql?, which requires obj to be OpenSSL::BN.
*/
static VALUE
-ossl_bn_eql(VALUE self, VALUE other)
+ossl_bn_eq(VALUE self, VALUE other)
{
- if (ossl_bn_cmp(self, other) == INT2FIX(0)) {
+ BIGNUM *bn1, *bn2;
+
+ GetBN(self, bn1);
+ /* BNPtr may raise, so we can't use here */
+ bn2 = try_convert_to_bnptr(other);
+
+ if (bn2 && !BN_cmp(bn1, bn2)) {
return Qtrue;
}
return Qfalse;
}
/*
+ * call-seq:
+ * bn.eql?(obj) => true or false
+ *
+ * Returns <code>true</code> only if <i>obj</i> is a
+ * <code>OpenSSL::BN</code> with the same value as <i>big</i>. Contrast this
+ * with OpenSSL::BN#==, which performs type conversions.
+ */
+static VALUE
+ossl_bn_eql(VALUE self, VALUE other)
+{
+ BIGNUM *bn1, *bn2;
+
+ if (!rb_obj_is_kind_of(other, cBN))
+ return Qfalse;
+ GetBN(self, bn1);
+ GetBN(other, bn2);
+
+ return BN_cmp(bn1, bn2) ? Qfalse : Qtrue;
+}
+
+/*
+ * call-seq:
+ * bn.hash => Integer
+ *
+ * Returns a hash code for this object.
+ *
+ * See also Object#hash.
+ */
+static VALUE
+ossl_bn_hash(VALUE self)
+{
+ BIGNUM *bn;
+ VALUE hash;
+ unsigned char *buf;
+ int len;
+
+ GetBN(self, bn);
+ len = BN_num_bytes(bn);
+ buf = xmalloc(len);
+ if (BN_bn2bin(bn, buf) != len) {
+ xfree(buf);
+ ossl_raise(eBNError, NULL);
+ }
+
+ hash = INT2FIX(rb_memhash(buf, len));
+ xfree(buf);
+
+ return hash;
+}
+
+/*
* call-seq:
* bn.prime? => true | false
* bn.prime?(checks) => true | false
@@ -982,8 +1044,9 @@ Init_ossl_bn(void)
rb_define_alias(cBN, "<=>", "cmp");
rb_define_method(cBN, "ucmp", ossl_bn_ucmp, 1);
rb_define_method(cBN, "eql?", ossl_bn_eql, 1);
- rb_define_alias(cBN, "==", "eql?");
- rb_define_alias(cBN, "===", "eql?");
+ rb_define_method(cBN, "hash", ossl_bn_hash, 0);
+ rb_define_method(cBN, "==", ossl_bn_eq, 1);
+ rb_define_alias(cBN, "===", "==");
rb_define_method(cBN, "zero?", ossl_bn_is_zero, 0);
rb_define_method(cBN, "one?", ossl_bn_is_one, 0);
/* is_word */
diff --git a/ext/openssl/ossl_cipher.c b/ext/openssl/ossl_cipher.c
index 09b021d9..d56b3411 100644
--- a/ext/openssl/ossl_cipher.c
+++ b/ext/openssl/ossl_cipher.c
@@ -116,7 +116,7 @@ ossl_cipher_initialize(VALUE self, VALUE str)
char *name;
unsigned char key[EVP_MAX_KEY_LENGTH];
- name = StringValuePtr(str);
+ name = StringValueCStr(str);
GetCipherInit(self, ctx);
if (ctx) {
ossl_raise(rb_eRuntimeError, "Cipher already inititalized!");
@@ -124,7 +124,7 @@ ossl_cipher_initialize(VALUE self, VALUE str)
AllocCipher(self, ctx);
EVP_CIPHER_CTX_init(ctx);
if (!(cipher = EVP_get_cipherbyname(name))) {
- ossl_raise(rb_eRuntimeError, "unsupported cipher algorithm (%s)", name);
+ ossl_raise(rb_eRuntimeError, "unsupported cipher algorithm (%"PRIsVALUE")", str);
}
/*
* The EVP which has EVP_CIPH_RAND_KEY flag (such as DES3) allows
@@ -158,16 +158,13 @@ ossl_cipher_copy(VALUE self, VALUE other)
return self;
}
-#ifdef HAVE_OBJ_NAME_DO_ALL_SORTED
static void*
add_cipher_name_to_ary(const OBJ_NAME *name, VALUE ary)
{
rb_ary_push(ary, rb_str_new2(name->name));
return NULL;
}
-#endif
-#ifdef HAVE_OBJ_NAME_DO_ALL_SORTED
/*
* call-seq:
* OpenSSL::Cipher.ciphers -> array[string...]
@@ -186,9 +183,6 @@ ossl_s_ciphers(VALUE self)
return ary;
}
-#else
-#define ossl_s_ciphers rb_f_notimplement
-#endif
/*
* call-seq:
@@ -480,15 +474,17 @@ static VALUE
ossl_cipher_set_key(VALUE self, VALUE key)
{
EVP_CIPHER_CTX *ctx;
+ int key_len;
StringValue(key);
GetCipher(self, ctx);
- if (RSTRING_LEN(key) < EVP_CIPHER_CTX_key_length(ctx))
- ossl_raise(eCipherError, "key length too short");
+ key_len = EVP_CIPHER_CTX_key_length(ctx);
+ if (RSTRING_LEN(key) != key_len)
+ ossl_raise(rb_eArgError, "key must be %d bytes", key_len);
if (EVP_CipherInit_ex(ctx, NULL, NULL, (unsigned char *)RSTRING_PTR(key), NULL, -1) != 1)
- ossl_raise(eCipherError, NULL);
+ ossl_raise(eCipherError, NULL);
return key;
}
@@ -512,12 +508,14 @@ static VALUE
ossl_cipher_set_iv(VALUE self, VALUE iv)
{
EVP_CIPHER_CTX *ctx;
+ int iv_len;
StringValue(iv);
GetCipher(self, ctx);
- if (RSTRING_LEN(iv) < EVP_CIPHER_CTX_iv_length(ctx))
- ossl_raise(eCipherError, "iv length too short");
+ iv_len = EVP_CIPHER_CTX_iv_length(ctx);
+ if (RSTRING_LEN(iv) != iv_len)
+ ossl_raise(rb_eArgError, "iv must be %d bytes", iv_len);
if (EVP_CipherInit_ex(ctx, NULL, NULL, NULL, (unsigned char *)RSTRING_PTR(iv), -1) != 1)
ossl_raise(eCipherError, NULL);
@@ -719,7 +717,6 @@ ossl_cipher_set_key_length(VALUE self, VALUE key_length)
return key_length;
}
-#if defined(HAVE_EVP_CIPHER_CTX_SET_PADDING)
/*
* call-seq:
* cipher.padding = integer -> integer
@@ -741,9 +738,6 @@ ossl_cipher_set_padding(VALUE self, VALUE padding)
ossl_raise(eCipherError, NULL);
return padding;
}
-#else
-#define ossl_cipher_set_padding rb_f_notimplement
-#endif
#define CIPHER_0ARG_INT(func) \
static VALUE \
diff --git a/ext/openssl/ossl_digest.c b/ext/openssl/ossl_digest.c
index 44968dd9..d137dc57 100644
--- a/ext/openssl/ossl_digest.c
+++ b/ext/openssl/ossl_digest.c
@@ -61,7 +61,7 @@ GetDigestPtr(VALUE obj)
ASN1_OBJECT_free(oid);
}
if(!md)
- ossl_raise(rb_eRuntimeError, "Unsupported digest algorithm (%s).", name);
+ ossl_raise(rb_eRuntimeError, "Unsupported digest algorithm (%"PRIsVALUE").", obj);
} else {
EVP_MD_CTX *ctx;
diff --git a/ext/openssl/ossl_engine.c b/ext/openssl/ossl_engine.c
index 890ec724..f84b1cff 100644
--- a/ext/openssl/ossl_engine.c
+++ b/ext/openssl/ossl_engine.c
@@ -9,7 +9,7 @@
*/
#include "ossl.h"
-#if defined(OSSL_ENGINE_ENABLED)
+#if !defined(OPENSSL_NO_ENGINE)
#define NewEngine(klass) \
TypedData_Wrap_Struct((klass), &ossl_engine_type, 0)
@@ -96,7 +96,7 @@ ossl_engine_s_load(int argc, VALUE *argv, VALUE klass)
ENGINE_load_builtin_engines();
return Qtrue;
}
- StringValue(name);
+ StringValueCStr(name);
#ifndef OPENSSL_NO_STATIC_ENGINE
#if HAVE_ENGINE_LOAD_DYNAMIC
OSSL_ENGINE_LOAD_IF_MATCH(dynamic);
@@ -148,7 +148,7 @@ ossl_engine_s_load(int argc, VALUE *argv, VALUE klass)
OSSL_ENGINE_LOAD_IF_MATCH(openbsd_dev_crypto);
#endif
OSSL_ENGINE_LOAD_IF_MATCH(openssl);
- rb_warning("no such builtin loader for `%s'", RSTRING_PTR(name));
+ rb_warning("no such builtin loader for `%"PRIsVALUE"'", name);
return Qnil;
#endif /* HAVE_ENGINE_LOAD_BUILTIN_ENGINES */
}
@@ -165,9 +165,7 @@ ossl_engine_s_load(int argc, VALUE *argv, VALUE klass)
static VALUE
ossl_engine_s_cleanup(VALUE self)
{
-#if defined(HAVE_ENGINE_CLEANUP)
ENGINE_cleanup();
-#endif
return Qnil;
}
@@ -213,7 +211,7 @@ ossl_engine_s_by_id(VALUE klass, VALUE id)
ENGINE *e;
VALUE obj;
- StringValue(id);
+ StringValueCStr(id);
ossl_engine_s_load(1, &id, klass);
obj = NewEngine(klass);
if(!(e = ENGINE_by_id(RSTRING_PTR(id))))
@@ -224,7 +222,7 @@ ossl_engine_s_by_id(VALUE klass, VALUE id)
ossl_raise(eEngineError, NULL);
ENGINE_ctrl(e, ENGINE_CTRL_SET_PASSWORD_CALLBACK,
0, NULL, (void(*)(void))ossl_pem_passwd_cb);
- ERR_clear_error();
+ ossl_clear_error();
return obj;
}
@@ -296,7 +294,6 @@ ossl_engine_finish(VALUE self)
return Qnil;
}
-#if defined(HAVE_ENGINE_GET_CIPHER)
/* Document-method: OpenSSL::Engine#cipher
*
* call-seq:
@@ -318,12 +315,10 @@ ossl_engine_get_cipher(VALUE self, VALUE name)
{
ENGINE *e;
const EVP_CIPHER *ciph, *tmp;
- char *s;
int nid;
- s = StringValuePtr(name);
- tmp = EVP_get_cipherbyname(s);
- if(!tmp) ossl_raise(eEngineError, "no such cipher `%s'", s);
+ tmp = EVP_get_cipherbyname(StringValueCStr(name));
+ if(!tmp) ossl_raise(eEngineError, "no such cipher `%"PRIsVALUE"'", name);
nid = EVP_CIPHER_nid(tmp);
GetEngine(self, e);
ciph = ENGINE_get_cipher(e, nid);
@@ -331,11 +326,7 @@ ossl_engine_get_cipher(VALUE self, VALUE name)
return ossl_cipher_new(ciph);
}
-#else
-#define ossl_engine_get_cipher rb_f_notimplement
-#endif
-#if defined(HAVE_ENGINE_GET_DIGEST)
/* Document-method: OpenSSL::Engine#digest
*
* call-seq:
@@ -357,12 +348,10 @@ ossl_engine_get_digest(VALUE self, VALUE name)
{
ENGINE *e;
const EVP_MD *md, *tmp;
- char *s;
int nid;
- s = StringValuePtr(name);
- tmp = EVP_get_digestbyname(s);
- if(!tmp) ossl_raise(eEngineError, "no such digest `%s'", s);
+ tmp = EVP_get_digestbyname(StringValueCStr(name));
+ if(!tmp) ossl_raise(eEngineError, "no such digest `%"PRIsVALUE"'", name);
nid = EVP_MD_nid(tmp);
GetEngine(self, e);
md = ENGINE_get_digest(e, nid);
@@ -370,9 +359,6 @@ ossl_engine_get_digest(VALUE self, VALUE name)
return ossl_digest_new(md);
}
-#else
-#define ossl_engine_get_digest rb_f_notimplement
-#endif
/* Document-method: OpenSSL::Engine#load_private_key
*
@@ -393,14 +379,10 @@ ossl_engine_load_privkey(int argc, VALUE *argv, VALUE self)
char *sid, *sdata;
rb_scan_args(argc, argv, "02", &id, &data);
- sid = NIL_P(id) ? NULL : StringValuePtr(id);
- sdata = NIL_P(data) ? NULL : StringValuePtr(data);
+ sid = NIL_P(id) ? NULL : StringValueCStr(id);
+ sdata = NIL_P(data) ? NULL : StringValueCStr(data);
GetEngine(self, e);
-#if OPENSSL_VERSION_NUMBER < 0x00907000L
- pkey = ENGINE_load_private_key(e, sid, sdata);
-#else
pkey = ENGINE_load_private_key(e, sid, NULL, sdata);
-#endif
if (!pkey) ossl_raise(eEngineError, NULL);
obj = ossl_pkey_new(pkey);
OSSL_PKEY_SET_PRIVATE(obj);
@@ -427,14 +409,10 @@ ossl_engine_load_pubkey(int argc, VALUE *argv, VALUE self)
char *sid, *sdata;
rb_scan_args(argc, argv, "02", &id, &data);
- sid = NIL_P(id) ? NULL : StringValuePtr(id);
- sdata = NIL_P(data) ? NULL : StringValuePtr(data);
+ sid = NIL_P(id) ? NULL : StringValueCStr(id);
+ sdata = NIL_P(data) ? NULL : StringValueCStr(data);
GetEngine(self, e);
-#if OPENSSL_VERSION_NUMBER < 0x00907000L
- pkey = ENGINE_load_public_key(e, sid, sdata);
-#else
pkey = ENGINE_load_public_key(e, sid, NULL, sdata);
-#endif
if (!pkey) ossl_raise(eEngineError, NULL);
return ossl_pkey_new(pkey);
@@ -487,10 +465,8 @@ ossl_engine_ctrl_cmd(int argc, VALUE *argv, VALUE self)
GetEngine(self, e);
rb_scan_args(argc, argv, "11", &cmd, &val);
- StringValue(cmd);
- if (!NIL_P(val)) StringValue(val);
- ret = ENGINE_ctrl_cmd_string(e, RSTRING_PTR(cmd),
- NIL_P(val) ? NULL : RSTRING_PTR(val), 0);
+ ret = ENGINE_ctrl_cmd_string(e, StringValueCStr(cmd),
+ NIL_P(val) ? NULL : StringValueCStr(val), 0);
if (!ret) ossl_raise(eEngineError, NULL);
return self;
@@ -585,12 +561,8 @@ Init_ossl_engine(void)
#ifdef ENGINE_METHOD_BN_MOD_EXP_CRT
DefEngineConst(METHOD_BN_MOD_EXP_CRT);
#endif
-#ifdef ENGINE_METHOD_CIPHERS
DefEngineConst(METHOD_CIPHERS);
-#endif
-#ifdef ENGINE_METHOD_DIGESTS
DefEngineConst(METHOD_DIGESTS);
-#endif
DefEngineConst(METHOD_ALL);
DefEngineConst(METHOD_NONE);
}
diff --git a/ext/openssl/ossl_ns_spki.c b/ext/openssl/ossl_ns_spki.c
index 35c2e3e5..e93b1b0a 100644
--- a/ext/openssl/ossl_ns_spki.c
+++ b/ext/openssl/ossl_ns_spki.c
@@ -86,15 +86,15 @@ ossl_spki_initialize(int argc, VALUE *argv, VALUE self)
return self;
}
StringValue(buffer);
- if (!(spki = NETSCAPE_SPKI_b64_decode(RSTRING_PTR(buffer), -1))) {
+ if (!(spki = NETSCAPE_SPKI_b64_decode(RSTRING_PTR(buffer), RSTRING_LENINT(buffer)))) {
+ ossl_clear_error();
p = (unsigned char *)RSTRING_PTR(buffer);
if (!(spki = d2i_NETSCAPE_SPKI(NULL, &p, RSTRING_LEN(buffer)))) {
ossl_raise(eSPKIError, NULL);
}
}
NETSCAPE_SPKI_free(DATA_PTR(self));
- DATA_PTR(self) = spki;
- ERR_clear_error();
+ SetSPKI(self, spki);
return self;
}
diff --git a/ext/openssl/ossl_ocsp.c b/ext/openssl/ossl_ocsp.c
index 02b67429..9f44bc20 100644
--- a/ext/openssl/ossl_ocsp.c
+++ b/ext/openssl/ossl_ocsp.c
@@ -10,7 +10,7 @@
*/
#include "ossl.h"
-#if defined(OSSL_OCSP_ENABLED)
+#if !defined(OPENSSL_NO_OCSP)
#define NewOCSPReq(klass) \
TypedData_Wrap_Struct((klass), &ossl_ocsp_request_type, 0)
@@ -1250,7 +1250,7 @@ Init_ossl_ocsp(void)
rb_define_const(mOCSP, "V_RESPID_KEY", INT2NUM(V_OCSP_RESPID_KEY));
}
-#else /* ! OSSL_OCSP_ENABLED */
+#else
void
Init_ossl_ocsp(void)
{
diff --git a/ext/openssl/ossl_ocsp.h b/ext/openssl/ossl_ocsp.h
index c5064fbc..21e2c99a 100644
--- a/ext/openssl/ossl_ocsp.h
+++ b/ext/openssl/ossl_ocsp.h
@@ -11,7 +11,7 @@
#if !defined(_OSSL_OCSP_H_)
#define _OSSL_OCSP_H_
-#if defined(OSSL_OCSP_ENABLED)
+#if !defined(OPENSSL_NO_OCSP)
extern VALUE mOCSP;
extern VALUE cOPCSReq;
extern VALUE cOPCSRes;
diff --git a/ext/openssl/ossl_pkcs12.c b/ext/openssl/ossl_pkcs12.c
index e5052d47..5f849723 100644
--- a/ext/openssl/ossl_pkcs12.c
+++ b/ext/openssl/ossl_pkcs12.c
@@ -100,19 +100,19 @@ ossl_pkcs12_s_create(int argc, VALUE *argv, VALUE self)
PKCS12 *p12;
rb_scan_args(argc, argv, "46", &pass, &name, &pkey, &cert, &ca, &key_nid, &cert_nid, &key_iter, &mac_iter, &keytype);
- passphrase = NIL_P(pass) ? NULL : StringValuePtr(pass);
- friendlyname = NIL_P(name) ? NULL : StringValuePtr(name);
+ passphrase = NIL_P(pass) ? NULL : StringValueCStr(pass);
+ friendlyname = NIL_P(name) ? NULL : StringValueCStr(name);
key = GetPKeyPtr(pkey);
x509 = GetX509CertPtr(cert);
x509s = NIL_P(ca) ? NULL : ossl_x509_ary2sk(ca);
/* TODO: make a VALUE to nid function */
if (!NIL_P(key_nid)) {
- if ((nkey = OBJ_txt2nid(StringValuePtr(key_nid))) == NID_undef)
- ossl_raise(rb_eArgError, "Unknown PBE algorithm %s", StringValuePtr(key_nid));
+ if ((nkey = OBJ_txt2nid(StringValueCStr(key_nid))) == NID_undef)
+ ossl_raise(rb_eArgError, "Unknown PBE algorithm %"PRIsVALUE, key_nid);
}
if (!NIL_P(cert_nid)) {
- if ((ncert = OBJ_txt2nid(StringValuePtr(cert_nid))) == NID_undef)
- ossl_raise(rb_eArgError, "Unknown PBE algorithm %s", StringValuePtr(cert_nid));
+ if ((ncert = OBJ_txt2nid(StringValueCStr(cert_nid))) == NID_undef)
+ ossl_raise(rb_eArgError, "Unknown PBE algorithm %"PRIsVALUE, cert_nid);
}
if (!NIL_P(key_iter))
kiter = NUM2INT(key_iter);
@@ -158,15 +158,19 @@ ossl_pkcs12_initialize(int argc, VALUE *argv, VALUE self)
PKCS12 *pkcs = DATA_PTR(self);
if(rb_scan_args(argc, argv, "02", &arg, &pass) == 0) return self;
- passphrase = NIL_P(pass) ? NULL : StringValuePtr(pass);
+ passphrase = NIL_P(pass) ? NULL : StringValueCStr(pass);
in = ossl_obj2bio(arg);
d2i_PKCS12_bio(in, &pkcs);
DATA_PTR(self) = pkcs;
BIO_free(in);
pkey = cert = ca = Qnil;
+ /* OpenSSL's bug; PKCS12_parse() puts errors even if it succeeds.
+ * Fixed in OpenSSL 1.0.0t, 1.0.1p, 1.0.2d */
+ ERR_set_mark();
if(!PKCS12_parse(pkcs, passphrase, &key, &x509, &x509s))
ossl_raise(ePKCS12Error, "PKCS12_parse");
+ ERR_pop_to_mark();
pkey = rb_protect((VALUE(*)_((VALUE)))ossl_pkey_new, (VALUE)key,
&st); /* NO DUP */
if(st) goto err;
diff --git a/ext/openssl/ossl_pkcs5.c b/ext/openssl/ossl_pkcs5.c
index 73d989e1..56ed65fb 100644
--- a/ext/openssl/ossl_pkcs5.c
+++ b/ext/openssl/ossl_pkcs5.c
@@ -48,7 +48,6 @@ ossl_pkcs5_pbkdf2_hmac(VALUE self, VALUE pass, VALUE salt, VALUE iter, VALUE key
#endif
-#ifdef HAVE_PKCS5_PBKDF2_HMAC_SHA1
/*
* call-seq:
* PKCS5.pbkdf2_hmac_sha1(pass, salt, iter, keylen) => string
@@ -81,9 +80,6 @@ ossl_pkcs5_pbkdf2_hmac_sha1(VALUE self, VALUE pass, VALUE salt, VALUE iter, VALU
return str;
}
-#else
-#define ossl_pkcs5_pbkdf2_hmac_sha1 rb_f_notimplement
-#endif
void
Init_ossl_pkcs5(void)
diff --git a/ext/openssl/ossl_pkcs7.c b/ext/openssl/ossl_pkcs7.c
index 9ca3abd7..5b7c07de 100644
--- a/ext/openssl/ossl_pkcs7.c
+++ b/ext/openssl/ossl_pkcs7.c
@@ -127,6 +127,22 @@ static const rb_data_type_t ossl_pkcs7_recip_info_type = {
* Public
* (MADE PRIVATE UNTIL SOMEBODY WILL NEED THEM)
*/
+static PKCS7_SIGNER_INFO *
+ossl_PKCS7_SIGNER_INFO_dup(const PKCS7_SIGNER_INFO *si)
+{
+ return (PKCS7_SIGNER_INFO *)ASN1_dup((i2d_of_void *)i2d_PKCS7_SIGNER_INFO,
+ (d2i_of_void *)d2i_PKCS7_SIGNER_INFO,
+ (char *)si);
+}
+
+static PKCS7_RECIP_INFO *
+ossl_PKCS7_RECIP_INFO_dup(const PKCS7_RECIP_INFO *si)
+{
+ return (PKCS7_RECIP_INFO *)ASN1_dup((i2d_of_void *)i2d_PKCS7_RECIP_INFO,
+ (d2i_of_void *)d2i_PKCS7_RECIP_INFO,
+ (char *)si);
+}
+
static VALUE
ossl_pkcs7si_new(PKCS7_SIGNER_INFO *p7si)
{
@@ -134,7 +150,7 @@ ossl_pkcs7si_new(PKCS7_SIGNER_INFO *p7si)
VALUE obj;
obj = NewPKCS7si(cPKCS7Signer);
- pkcs7 = p7si ? PKCS7_SIGNER_INFO_dup(p7si) : PKCS7_SIGNER_INFO_new();
+ pkcs7 = p7si ? ossl_PKCS7_SIGNER_INFO_dup(p7si) : PKCS7_SIGNER_INFO_new();
if (!pkcs7) ossl_raise(ePKCS7Error, NULL);
SetPKCS7si(obj, pkcs7);
@@ -147,7 +163,7 @@ DupPKCS7SignerPtr(VALUE obj)
PKCS7_SIGNER_INFO *p7si, *pkcs7;
SafeGetPKCS7si(obj, p7si);
- if (!(pkcs7 = PKCS7_SIGNER_INFO_dup(p7si))) {
+ if (!(pkcs7 = ossl_PKCS7_SIGNER_INFO_dup(p7si))) {
ossl_raise(ePKCS7Error, NULL);
}
@@ -161,7 +177,7 @@ ossl_pkcs7ri_new(PKCS7_RECIP_INFO *p7ri)
VALUE obj;
obj = NewPKCS7ri(cPKCS7Recipient);
- pkcs7 = p7ri ? PKCS7_RECIP_INFO_dup(p7ri) : PKCS7_RECIP_INFO_new();
+ pkcs7 = p7ri ? ossl_PKCS7_RECIP_INFO_dup(p7ri) : PKCS7_RECIP_INFO_new();
if (!pkcs7) ossl_raise(ePKCS7Error, NULL);
SetPKCS7ri(obj, pkcs7);
@@ -174,7 +190,7 @@ DupPKCS7RecipientPtr(VALUE obj)
PKCS7_RECIP_INFO *p7ri, *pkcs7;
SafeGetPKCS7ri(obj, p7ri);
- if (!(pkcs7 = PKCS7_RECIP_INFO_dup(p7ri))) {
+ if (!(pkcs7 = ossl_PKCS7_RECIP_INFO_dup(p7ri))) {
ossl_raise(ePKCS7Error, NULL);
}
@@ -429,12 +445,13 @@ ossl_pkcs7_sym2typeid(VALUE sym)
{ "digest", NID_pkcs7_digest },
};
- if (RB_TYPE_P(sym, T_SYMBOL)) sym = rb_sym2str(sym);
+ if (SYMBOL_P(sym)) sym = rb_sym2str(sym);
else StringValue(sym);
RSTRING_GETMEM(sym, s, l);
+
for(i = 0; ; i++){
if(i == numberof(p7_type_tab))
- ossl_raise(ePKCS7Error, "unknown type \"%s\"", s);
+ ossl_raise(ePKCS7Error, "unknown type \"%"PRIsVALUE"\"", sym);
if(strlen(p7_type_tab[i].name) != l) continue;
if(strcmp(p7_type_tab[i].name, s) == 0){
ret = p7_type_tab[i].nid;
@@ -779,7 +796,7 @@ ossl_pkcs7_verify(int argc, VALUE *argv, VALUE self)
if (ok < 0) ossl_raise(ePKCS7Error, NULL);
msg = ERR_reason_error_string(ERR_get_error());
ossl_pkcs7_set_err_string(self, msg ? rb_str_new2(msg) : Qnil);
- ERR_clear_error();
+ ossl_clear_error();
data = ossl_membio2str(out);
ossl_pkcs7_set_data(self, data);
sk_X509_pop_free(x509s, X509_free);
diff --git a/ext/openssl/ossl_pkey.c b/ext/openssl/ossl_pkey.c
index e758c9e3..e4ae549f 100644
--- a/ext/openssl/ossl_pkey.c
+++ b/ext/openssl/ossl_pkey.c
@@ -20,20 +20,6 @@ ID id_private_q;
/*
* callback for generating keys
*/
-void
-ossl_generate_cb(int p, int n, void *arg)
-{
- VALUE ary;
-
- ary = rb_ary_new2(2);
- rb_ary_store(ary, 0, INT2NUM(p));
- rb_ary_store(ary, 1, INT2NUM(n));
-
- rb_yield(ary);
-}
-
-#if HAVE_BN_GENCB
-/* OpenSSL 2nd version of GN generation callback */
int
ossl_generate_cb_2(int p, int n, BN_GENCB *cb)
{
@@ -66,7 +52,6 @@ ossl_generate_cb_stop(void *ptr)
struct ossl_generate_cb_arg *arg = (struct ossl_generate_cb_arg *)ptr;
arg->stop = 1;
}
-#endif
static void
ossl_evp_pkey_free(void *ptr)
@@ -121,8 +106,8 @@ ossl_pkey_new_from_file(VALUE filename)
FILE *fp;
EVP_PKEY *pkey;
- SafeStringValue(filename);
- if (!(fp = fopen(RSTRING_PTR(filename), "r"))) {
+ rb_check_safe_obj(filename);
+ if (!(fp = fopen(StringValueCStr(filename), "r"))) {
ossl_raise(ePKeyError, "%s", strerror(errno));
}
rb_fd_fix_cloexec(fileno(fp));
@@ -152,27 +137,21 @@ ossl_pkey_new_from_file(VALUE filename)
static VALUE
ossl_pkey_new_from_data(int argc, VALUE *argv, VALUE self)
{
- EVP_PKEY *pkey;
- BIO *bio;
- VALUE data, pass;
- char *passwd = NULL;
+ EVP_PKEY *pkey;
+ BIO *bio;
+ VALUE data, pass;
- rb_scan_args(argc, argv, "11", &data, &pass);
+ rb_scan_args(argc, argv, "11", &data, &pass);
+ pass = ossl_pem_passwd_value(pass);
- bio = ossl_obj2bio(data);
- if (!(pkey = d2i_PrivateKey_bio(bio, NULL))) {
+ bio = ossl_obj2bio(data);
+ if (!(pkey = d2i_PrivateKey_bio(bio, NULL))) {
OSSL_BIO_reset(bio);
- if (!NIL_P(pass)) {
- passwd = StringValuePtr(pass);
- }
- if (!(pkey = PEM_read_bio_PrivateKey(bio, NULL, ossl_pem_passwd_cb, passwd))) {
+ if (!(pkey = PEM_read_bio_PrivateKey(bio, NULL, ossl_pem_passwd_cb, (void *)pass))) {
OSSL_BIO_reset(bio);
if (!(pkey = d2i_PUBKEY_bio(bio, NULL))) {
OSSL_BIO_reset(bio);
- if (!NIL_P(pass)) {
- passwd = StringValuePtr(pass);
- }
- pkey = PEM_read_bio_PUBKEY(bio, NULL, ossl_pem_passwd_cb, passwd);
+ pkey = PEM_read_bio_PUBKEY(bio, NULL, ossl_pem_passwd_cb, (void *)pass);
}
}
}
@@ -374,7 +353,7 @@ Init_ossl_pkey(void)
* algorithm consists of two parts: a public key that may be distributed
* to others and a private key that needs to remain secret.
*
- * Messages encrypted with a public key can only be encrypted by
+ * Messages encrypted with a public key can only be decrypted by
* recipients that are in possession of the associated private key.
* Since public key algorithms are considerably slower than symmetric
* key algorithms (cf. OpenSSL::Cipher) they are often used to establish
diff --git a/ext/openssl/ossl_pkey.h b/ext/openssl/ossl_pkey.h
index 7288d5af..b806d63e 100644
--- a/ext/openssl/ossl_pkey.h
+++ b/ext/openssl/ossl_pkey.h
@@ -40,9 +40,6 @@ extern const rb_data_type_t ossl_evp_pkey_type;
GetPKey((obj), (pkey)); \
} while (0)
-void ossl_generate_cb(int, int, void *);
-#define HAVE_BN_GENCB defined(HAVE_RSA_GENERATE_KEY_EX) || defined(HAVE_DH_GENERATE_PARAMETERS_EX) || defined(HAVE_DSA_GENERATE_PARAMETERS_EX)
-#if HAVE_BN_GENCB
struct ossl_generate_cb_arg {
int yield;
int stop;
@@ -50,7 +47,6 @@ struct ossl_generate_cb_arg {
};
int ossl_generate_cb_2(int p, int n, BN_GENCB *cb);
void ossl_generate_cb_stop(void *ptr);
-#endif
VALUE ossl_pkey_new(EVP_PKEY *);
VALUE ossl_pkey_new_from_file(VALUE);
diff --git a/ext/openssl/ossl_pkey_dh.c b/ext/openssl/ossl_pkey_dh.c
index 2f79bfb2..ac951a6e 100644
--- a/ext/openssl/ossl_pkey_dh.c
+++ b/ext/openssl/ossl_pkey_dh.c
@@ -20,7 +20,7 @@
#define DH_HAS_PRIVATE(dh) ((dh)->priv_key)
-#ifdef OSSL_ENGINE_ENABLED
+#if !defined(OPENSSL_NO_ENGINE)
# define DH_PRIVATE(dh) (DH_HAS_PRIVATE(dh) || (dh)->engine)
#else
# define DH_PRIVATE(dh) DH_HAS_PRIVATE(dh)
@@ -82,7 +82,6 @@ ossl_dh_new(EVP_PKEY *pkey)
/*
* Private
*/
-#if defined(HAVE_DH_GENERATE_PARAMETERS_EX) && HAVE_BN_GENCB
struct dh_blocking_gen_arg {
DH *dh;
int size;
@@ -98,12 +97,10 @@ dh_blocking_gen(void *arg)
gen->result = DH_generate_parameters_ex(gen->dh, gen->size, gen->gen, gen->cb);
return 0;
}
-#endif
static DH *
dh_generate(int size, int gen)
{
-#if defined(HAVE_DH_GENERATE_PARAMETERS_EX) && HAVE_BN_GENCB
BN_GENCB cb;
struct ossl_generate_cb_arg cb_arg;
struct dh_blocking_gen_arg gen_arg;
@@ -129,15 +126,13 @@ dh_generate(int size, int gen)
if (!gen_arg.result) {
DH_free(dh);
- if (cb_arg.state) rb_jump_tag(cb_arg.state);
+ if (cb_arg.state) {
+ /* Clear OpenSSL error queue before re-raising. */
+ ossl_clear_error();
+ rb_jump_tag(cb_arg.state);
+ }
return 0;
}
-#else
- DH *dh;
-
- dh = DH_generate_parameters(size, gen, rb_block_given_p() ? ossl_generate_cb : NULL, NULL);
- if (!dh) return 0;
-#endif
if (!DH_generate_key(dh)) {
DH_free(dh);
@@ -506,6 +501,8 @@ ossl_dh_compute_key(VALUE self, VALUE pub)
GetPKeyDH(self, pkey);
dh = pkey->pkey.dh;
+ if (!dh->p)
+ ossl_raise(eDHError, "incomplete DH");
pub_key = GetBNPtr(pub);
len = DH_size(dh);
str = rb_str_new(0, len);
diff --git a/ext/openssl/ossl_pkey_dsa.c b/ext/openssl/ossl_pkey_dsa.c
index 04900cc6..704fad6d 100644
--- a/ext/openssl/ossl_pkey_dsa.c
+++ b/ext/openssl/ossl_pkey_dsa.c
@@ -76,7 +76,6 @@ ossl_dsa_new(EVP_PKEY *pkey)
/*
* Private
*/
-#if defined(HAVE_DSA_GENERATE_PARAMETERS_EX) && HAVE_BN_GENCB
struct dsa_blocking_gen_arg {
DSA *dsa;
int size;
@@ -95,12 +94,10 @@ dsa_blocking_gen(void *arg)
gen->result = DSA_generate_parameters_ex(gen->dsa, gen->size, gen->seed, gen->seed_len, gen->counter, gen->h, gen->cb);
return 0;
}
-#endif
static DSA *
dsa_generate(int size)
{
-#if defined(HAVE_DSA_GENERATE_PARAMETERS_EX) && HAVE_BN_GENCB
BN_GENCB cb;
struct ossl_generate_cb_arg cb_arg;
struct dsa_blocking_gen_arg gen_arg;
@@ -135,22 +132,16 @@ dsa_generate(int size)
}
if (!gen_arg.result) {
DSA_free(dsa);
- if (cb_arg.state) rb_jump_tag(cb_arg.state);
- return 0;
- }
-#else
- DSA *dsa;
- unsigned char seed[20];
- int seed_len = 20, counter;
- unsigned long h;
-
- if (RAND_bytes(seed, seed_len) <= 0) {
+ if (cb_arg.state) {
+ /* Clear OpenSSL error queue before re-raising. By the way, the
+ * documentation of DSA_generate_parameters_ex() says the error code
+ * can be obtained by ERR_get_error(), but the default
+ * implementation, dsa_builtin_paramgen() doesn't put any error... */
+ ossl_clear_error();
+ rb_jump_tag(cb_arg.state);
+ }
return 0;
}
- dsa = DSA_generate_parameters(size, seed, seed_len, &counter, &h,
- rb_block_given_p() ? ossl_generate_cb : NULL, NULL);
- if(!dsa) return 0;
-#endif
if (!DSA_generate_key(dsa)) {
DSA_free(dsa);
@@ -209,7 +200,6 @@ ossl_dsa_initialize(int argc, VALUE *argv, VALUE self)
EVP_PKEY *pkey;
DSA *dsa;
BIO *in;
- char *passwd = NULL;
VALUE arg, pass;
GetPKey(self, pkey);
@@ -222,10 +212,10 @@ ossl_dsa_initialize(int argc, VALUE *argv, VALUE self)
}
}
else {
- if (!NIL_P(pass)) passwd = StringValuePtr(pass);
+ pass = ossl_pem_passwd_value(pass);
arg = ossl_to_der_if_possible(arg);
in = ossl_obj2bio(arg);
- dsa = PEM_read_bio_DSAPrivateKey(in, NULL, ossl_pem_passwd_cb, passwd);
+ dsa = PEM_read_bio_DSAPrivateKey(in, NULL, ossl_pem_passwd_cb, (void *)pass);
if (!dsa) {
OSSL_BIO_reset(in);
dsa = PEM_read_bio_DSA_PUBKEY(in, NULL, NULL, NULL);
@@ -240,11 +230,14 @@ ossl_dsa_initialize(int argc, VALUE *argv, VALUE self)
}
if (!dsa) {
OSSL_BIO_reset(in);
+#define PEM_read_bio_DSAPublicKey(bp,x,cb,u) (DSA *)PEM_ASN1_read_bio( \
+ (d2i_of_void *)d2i_DSAPublicKey, PEM_STRING_DSA_PUBLIC, (bp), (void **)(x), (cb), (u))
dsa = PEM_read_bio_DSAPublicKey(in, NULL, NULL, NULL);
+#undef PEM_read_bio_DSAPublicKey
}
BIO_free(in);
if (!dsa) {
- ERR_clear_error();
+ ossl_clear_error();
ossl_raise(eDSAError, "Neither PUB key nor PRIV key");
}
}
@@ -313,26 +306,20 @@ ossl_dsa_export(int argc, VALUE *argv, VALUE self)
EVP_PKEY *pkey;
BIO *out;
const EVP_CIPHER *ciph = NULL;
- char *passwd = NULL;
VALUE cipher, pass, str;
GetPKeyDSA(self, pkey);
rb_scan_args(argc, argv, "02", &cipher, &pass);
if (!NIL_P(cipher)) {
ciph = GetCipherPtr(cipher);
- if (!NIL_P(pass)) {
- StringValue(pass);
- if (RSTRING_LENINT(pass) < OSSL_MIN_PWD_LEN)
- ossl_raise(eOSSLError, "OpenSSL requires passwords to be at least four characters long");
- passwd = RSTRING_PTR(pass);
- }
+ pass = ossl_pem_passwd_value(pass);
}
if (!(out = BIO_new(BIO_s_mem()))) {
ossl_raise(eDSAError, NULL);
}
if (DSA_HAS_PRIVATE(pkey->pkey.dsa)) {
if (!PEM_write_bio_DSAPrivateKey(out, pkey->pkey.dsa, ciph,
- NULL, 0, ossl_pem_passwd_cb, passwd)){
+ NULL, 0, ossl_pem_passwd_cb, (void *)pass)){
BIO_free(out);
ossl_raise(eDSAError, NULL);
}
@@ -460,7 +447,10 @@ ossl_dsa_to_public_key(VALUE self)
GetPKeyDSA(self, pkey);
/* err check performed by dsa_instance */
+#define DSAPublicKey_dup(dsa) (DSA *)ASN1_dup( \
+ (i2d_of_void *)i2d_DSAPublicKey, (d2i_of_void *)d2i_DSAPublicKey, (char *)(dsa))
dsa = DSAPublicKey_dup(pkey->pkey.dsa);
+#undef DSAPublicKey_dup
obj = dsa_instance(CLASS_OF(self), dsa);
if (obj == Qfalse) {
DSA_free(dsa);
@@ -498,10 +488,11 @@ ossl_dsa_sign(VALUE self, VALUE data)
VALUE str;
GetPKeyDSA(self, pkey);
- StringValue(data);
- if (!DSA_PRIVATE(self, pkey->pkey.dsa)) {
+ if (!pkey->pkey.dsa->q)
+ ossl_raise(eDSAError, "incomplete DSA");
+ if (!DSA_PRIVATE(self, pkey->pkey.dsa))
ossl_raise(eDSAError, "Private DSA key needed!");
- }
+ StringValue(data);
str = rb_str_new(0, ossl_dsa_buf_size(pkey));
if (!DSA_sign(0, (unsigned char *)RSTRING_PTR(data), RSTRING_LENINT(data),
(unsigned char *)RSTRING_PTR(str),
diff --git a/ext/openssl/ossl_pkey_ec.c b/ext/openssl/ossl_pkey_ec.c
index c93e3cfb..958e7105 100644
--- a/ext/openssl/ossl_pkey_ec.c
+++ b/ext/openssl/ossl_pkey_ec.c
@@ -149,6 +149,69 @@ VALUE ossl_ec_new(EVP_PKEY *pkey)
return obj;
}
+/*
+ * Creates a new EC_KEY on the EC group obj. arg can be an EC::Group or a String
+ * representing an OID.
+ */
+static EC_KEY *
+ec_key_new_from_group(VALUE arg)
+{
+ EC_KEY *ec;
+
+ if (rb_obj_is_kind_of(arg, cEC_GROUP)) {
+ EC_GROUP *group;
+
+ SafeRequire_EC_GROUP(arg, group);
+
+ if (!(ec = EC_KEY_new()))
+ ossl_raise(eECError, NULL);
+
+ if (!EC_KEY_set_group(ec, group)) {
+ EC_KEY_free(ec);
+ ossl_raise(eECError, NULL);
+ }
+ } else {
+ int nid = OBJ_sn2nid(StringValueCStr(arg));
+
+ if (nid == NID_undef)
+ ossl_raise(eECError, "invalid curve name");
+
+ if (!(ec = EC_KEY_new_by_curve_name(nid)))
+ ossl_raise(eECError, NULL);
+
+ EC_KEY_set_asn1_flag(ec, OPENSSL_EC_NAMED_CURVE);
+ EC_KEY_set_conv_form(ec, POINT_CONVERSION_UNCOMPRESSED);
+ }
+
+ return ec;
+}
+
+/*
+ * call-seq:
+ * EC.generate(ec_group) -> ec
+ * EC.generate(string) -> ec
+ *
+ * Creates a new EC instance with a new random private and public key.
+ */
+static VALUE
+ossl_ec_key_s_generate(VALUE klass, VALUE arg)
+{
+ EC_KEY *ec;
+ VALUE obj;
+
+ ec = ec_key_new_from_group(arg);
+
+ obj = ec_instance(klass, ec);
+ if (obj == Qfalse) {
+ EC_KEY_free(ec);
+ ossl_raise(eECError, NULL);
+ }
+
+ if (!EC_KEY_generate_key(ec))
+ ossl_raise(eECError, "EC_KEY_generate_key");
+
+ return obj;
+}
/* call-seq:
* OpenSSL::PKey::EC.new()
@@ -165,10 +228,8 @@ VALUE ossl_ec_new(EVP_PKEY *pkey)
static VALUE ossl_ec_key_initialize(int argc, VALUE *argv, VALUE self)
{
EVP_PKEY *pkey;
- EC_KEY *ec = NULL;
+ EC_KEY *ec;
VALUE arg, pass;
- VALUE group = Qnil;
- char *passwd = NULL;
GetPKey(self, pkey);
if (pkey->pkey.ec)
@@ -177,58 +238,43 @@ static VALUE ossl_ec_key_initialize(int argc, VALUE *argv, VALUE self)
rb_scan_args(argc, argv, "02", &arg, &pass);
if (NIL_P(arg)) {
- ec = EC_KEY_new();
+ if (!(ec = EC_KEY_new()))
+ ossl_raise(eECError, NULL);
+ } else if (rb_obj_is_kind_of(arg, cEC)) {
+ EC_KEY *other_ec = NULL;
+
+ SafeRequire_EC_KEY(arg, other_ec);
+ if (!(ec = EC_KEY_dup(other_ec)))
+ ossl_raise(eECError, NULL);
+ } else if (rb_obj_is_kind_of(arg, cEC_GROUP)) {
+ ec = ec_key_new_from_group(arg);
} else {
- if (rb_obj_is_kind_of(arg, cEC)) {
- EC_KEY *other_ec = NULL;
-
- SafeRequire_EC_KEY(arg, other_ec);
- ec = EC_KEY_dup(other_ec);
- } else if (rb_obj_is_kind_of(arg, cEC_GROUP)) {
- ec = EC_KEY_new();
- group = arg;
- } else {
- BIO *in = ossl_obj2bio(arg);
-
- if (!NIL_P(pass)) {
- passwd = StringValuePtr(pass);
- }
- ec = PEM_read_bio_ECPrivateKey(in, NULL, ossl_pem_passwd_cb, passwd);
- if (!ec) {
- OSSL_BIO_reset(in);
- ec = PEM_read_bio_EC_PUBKEY(in, NULL, ossl_pem_passwd_cb, passwd);
- }
- if (!ec) {
- OSSL_BIO_reset(in);
- ec = d2i_ECPrivateKey_bio(in, NULL);
- }
- if (!ec) {
- OSSL_BIO_reset(in);
- ec = d2i_EC_PUBKEY_bio(in, NULL);
- }
-
- BIO_free(in);
-
- if (ec == NULL) {
- const char *name = StringValueCStr(arg);
- int nid = OBJ_sn2nid(name);
+ BIO *in;
- (void)ERR_get_error();
- if (nid == NID_undef)
- ossl_raise(eECError, "unknown curve name (%s)\n", name);
+ pass = ossl_pem_passwd_value(pass);
+ in = ossl_obj2bio(arg);
- if ((ec = EC_KEY_new_by_curve_name(nid)) == NULL)
- ossl_raise(eECError, "unable to create curve (%s)\n", name);
+ ec = PEM_read_bio_ECPrivateKey(in, NULL, ossl_pem_passwd_cb, (void *)pass);
+ if (!ec) {
+ OSSL_BIO_reset(in);
+ ec = PEM_read_bio_EC_PUBKEY(in, NULL, ossl_pem_passwd_cb, (void *)pass);
+ }
+ if (!ec) {
+ OSSL_BIO_reset(in);
+ ec = d2i_ECPrivateKey_bio(in, NULL);
+ }
+ if (!ec) {
+ OSSL_BIO_reset(in);
+ ec = d2i_EC_PUBKEY_bio(in, NULL);
+ }
+ BIO_free(in);
- EC_KEY_set_asn1_flag(ec, OPENSSL_EC_NAMED_CURVE);
- EC_KEY_set_conv_form(ec, POINT_CONVERSION_UNCOMPRESSED);
- }
- }
+ if (!ec) {
+ ossl_clear_error();
+ ec = ec_key_new_from_group(arg);
+ }
}
- if (ec == NULL)
- ossl_raise(eECError, NULL);
-
if (!EVP_PKEY_assign_EC_KEY(pkey, ec)) {
EC_KEY_free(ec);
ossl_raise(eECError, "EVP_PKEY_assign_EC_KEY");
@@ -236,9 +282,6 @@ static VALUE ossl_ec_key_initialize(int argc, VALUE *argv, VALUE self)
rb_iv_set(self, "@group", Qnil);
- if (!NIL_P(group))
- rb_funcall(self, rb_intern("group="), 1, arg);
-
return self;
}
@@ -439,32 +482,34 @@ static VALUE ossl_ec_key_set_public_key(VALUE self, VALUE public_key)
/*
* call-seq:
- * key.public_key? => true or false
+ * key.public? => true or false
*
- * Both public_key? and private_key? may return false at the same time unlike other PKey classes.
+ * Returns whether this EC instance has a public key. The public key
+ * (EC::Point) can be retrieved with EC#public_key.
*/
-static VALUE ossl_ec_key_is_public_key(VALUE self)
+static VALUE ossl_ec_key_is_public(VALUE self)
{
EC_KEY *ec;
Require_EC_KEY(self, ec);
- return (EC_KEY_get0_public_key(ec) ? Qtrue : Qfalse);
+ return EC_KEY_get0_public_key(ec) ? Qtrue : Qfalse;
}
/*
* call-seq:
- * key.private_key? => true or false
+ * key.private? => true or false
*
- * Both public_key? and private_key? may return false at the same time unlike other PKey classes.
+ * Returns whether this EC instance has a private key. The private key (BN) can
+ * be retrieved with EC#private_key.
*/
-static VALUE ossl_ec_key_is_private_key(VALUE self)
+static VALUE ossl_ec_key_is_private(VALUE self)
{
EC_KEY *ec;
Require_EC_KEY(self, ec);
- return (EC_KEY_get0_private_key(ec) ? Qtrue : Qfalse);
+ return EC_KEY_get0_private_key(ec) ? Qtrue : Qfalse;
}
static VALUE ossl_ec_key_to_string(VALUE self, VALUE ciph, VALUE pass, int format)
@@ -473,7 +518,6 @@ static VALUE ossl_ec_key_to_string(VALUE self, VALUE ciph, VALUE pass, int forma
BIO *out;
int i = -1;
int private = 0;
- char *password = NULL;
VALUE str;
Require_EC_KEY(self, ec);
@@ -493,20 +537,12 @@ static VALUE ossl_ec_key_to_string(VALUE self, VALUE ciph, VALUE pass, int forma
switch(format) {
case EXPORT_PEM:
if (private) {
- const EVP_CIPHER *cipher;
+ const EVP_CIPHER *cipher = NULL;
if (!NIL_P(ciph)) {
cipher = GetCipherPtr(ciph);
- if (!NIL_P(pass)) {
- StringValue(pass);
- if (RSTRING_LENINT(pass) < OSSL_MIN_PWD_LEN)
- ossl_raise(eOSSLError, "OpenSSL requires passwords to be at least four characters long");
- password = RSTRING_PTR(pass);
- }
+ pass = ossl_pem_passwd_value(pass);
}
- else {
- cipher = NULL;
- }
- i = PEM_write_bio_ECPrivateKey(out, ec, cipher, NULL, 0, NULL, password);
+ i = PEM_write_bio_ECPrivateKey(out, ec, cipher, NULL, 0, ossl_pem_passwd_cb, (void *)pass);
} else {
i = PEM_write_bio_EC_PUBKEY(out, ec);
}
@@ -592,9 +628,17 @@ static VALUE ossl_ec_key_to_text(VALUE self)
/*
* call-seq:
- * key.generate_key => self
+ * key.generate_key! => self
+ *
+ * Generates a new random private and public key.
+ *
+ * See also the OpenSSL documentation for EC_KEY_generate_key()
*
- * See the OpenSSL documentation for EC_KEY_generate_key()
+ * === Example
+ * ec = OpenSSL::PKey::EC.new("prime256v1")
+ * p ec.private_key # => nil
+ * ec.generate_key!
+ * p ec.private_key # => #<OpenSSL::BN XXXXXX>
*/
static VALUE ossl_ec_key_generate_key(VALUE self)
{
@@ -808,13 +852,13 @@ static VALUE ossl_ec_group_initialize(int argc, VALUE *argv, VALUE self)
const char *name = StringValueCStr(arg1);
int nid = OBJ_sn2nid(name);
- (void)ERR_get_error();
+ ossl_clear_error(); /* ignore errors in d2i_ECPKParameters_bio() */
if (nid == NID_undef)
- ossl_raise(eEC_GROUP, "unknown curve name (%s)", name);
+ ossl_raise(eEC_GROUP, "unknown curve name (%"PRIsVALUE")", arg1);
group = EC_GROUP_new_by_curve_name(nid);
if (group == NULL)
- ossl_raise(eEC_GROUP, "unable to create curve (%s)", name);
+ ossl_raise(eEC_GROUP, "unable to create curve (%"PRIsVALUE")", arg1);
EC_GROUP_set_asn1_flag(group, OPENSSL_EC_NAMED_CURVE);
EC_GROUP_set_point_conversion_form(group, POINT_CONVERSION_UNCOMPRESSED);
@@ -1500,74 +1544,84 @@ static VALUE ossl_ec_point_to_bn(VALUE self)
/*
* call-seq:
- * point.mul(bn) => point
- * point.mul(bn, bn) => point
- * point.mul([bn], [point]) => point
- * point.mul([bn], [point], bn) => point
+ * point.mul(bn1 [, bn2]) => point
+ * point.mul(bns, points [, bn2]) => point
+ *
+ * Performs elliptic curve point multiplication.
+ *
+ * The first form calculates <tt>bn1 * point + bn2 * G</tt>, where +G+ is the
+ * generator of the group of +point+. +bn2+ may be ommitted, and in that case,
+ * the result is just <tt>bn1 * point</tt>.
+ *
+ * The second form calculates <tt>bns[0] * point + bns[1] * points[0] + ...
+ * + bns[-1] * points[-1] + bn2 * G</tt>. +bn2+ may be ommitted. +bns+ must be
+ * an array of OpenSSL::BN. +points+ must be an array of
+ * OpenSSL::PKey::EC::Point. Please note that <tt>points[0]</tt> is not
+ * multiplied by <tt>bns[0]</tt>, but <tt>bns[1]</tt>.
*/
static VALUE ossl_ec_point_mul(int argc, VALUE *argv, VALUE self)
{
- EC_POINT *point1, *point2;
+ EC_POINT *point_self, *point_result;
const EC_GROUP *group;
VALUE group_v = rb_iv_get(self, "@group");
- VALUE bn_v1, bn_v2, r, points_v;
- BIGNUM *bn1 = NULL, *bn2 = NULL;
+ VALUE arg1, arg2, arg3, result;
+ const BIGNUM *bn_g = NULL;
- Require_EC_POINT(self, point1);
+ Require_EC_POINT(self, point_self);
SafeRequire_EC_GROUP(group_v, group);
- r = rb_obj_alloc(cEC_POINT);
- ossl_ec_point_initialize(1, &group_v, r);
- Require_EC_POINT(r, point2);
+ result = rb_obj_alloc(cEC_POINT);
+ ossl_ec_point_initialize(1, &group_v, result);
+ Require_EC_POINT(result, point_result);
- argc = rb_scan_args(argc, argv, "12", &bn_v1, &points_v, &bn_v2);
+ rb_scan_args(argc, argv, "12", &arg1, &arg2, &arg3);
+ if (rb_obj_is_kind_of(arg1, cBN)) {
+ BIGNUM *bn = GetBNPtr(arg1);
+ if (argc >= 2)
+ bn_g = GetBNPtr(arg2);
- if (rb_obj_is_kind_of(bn_v1, cBN)) {
- bn1 = GetBNPtr(bn_v1);
- if (argc >= 2) {
- bn2 = GetBNPtr(points_v);
- }
- if (EC_POINT_mul(group, point2, bn2, point1, bn1, ossl_bn_ctx) != 1)
- ossl_raise(eEC_POINT, "Multiplication failed");
+ if (EC_POINT_mul(group, point_result, bn_g, point_self, bn, ossl_bn_ctx) != 1)
+ ossl_raise(eEC_POINT, NULL);
} else {
- size_t i, points_len, bignums_len;
- const EC_POINT **points;
- const BIGNUM **bignums;
-
- Check_Type(bn_v1, T_ARRAY);
- bignums_len = RARRAY_LEN(bn_v1);
- bignums = (const BIGNUM **)OPENSSL_malloc(bignums_len * (int)sizeof(BIGNUM *));
-
- for (i = 0; i < bignums_len; ++i) {
- bignums[i] = GetBNPtr(rb_ary_entry(bn_v1, i));
- }
-
- if (!rb_obj_is_kind_of(points_v, rb_cArray)) {
- OPENSSL_free((void *)bignums);
- rb_raise(rb_eTypeError, "Argument2 must be an array");
- }
-
- rb_ary_unshift(points_v, self);
- points_len = RARRAY_LEN(points_v);
- points = (const EC_POINT **)OPENSSL_malloc(points_len * (int)sizeof(EC_POINT *));
-
- for (i = 0; i < points_len; ++i) {
- Get_EC_POINT(rb_ary_entry(points_v, i), points[i]);
- }
+ /*
+ * bignums | arg1[0] | arg1[1] | arg1[2] | ...
+ * points | self | arg2[0] | arg2[1] | ...
+ */
+ long i, num;
+ VALUE tmp_p, tmp_b;
+ const EC_POINT **points;
+ const BIGNUM **bignums;
+
+ if (!rb_obj_is_kind_of(arg1, rb_cArray) ||
+ !rb_obj_is_kind_of(arg2, rb_cArray))
+ ossl_raise(rb_eTypeError, "points must be array");
+ if (RARRAY_LEN(arg1) != RARRAY_LEN(arg2) + 1) /* arg2 must be 1 larger */
+ ossl_raise(rb_eArgError, "bns must be 1 longer than points; see the documentation");
+
+ num = RARRAY_LEN(arg1);
+ bignums = ALLOCV_N(const BIGNUM *, tmp_b, num);
+ for (i = 0; i < num; i++)
+ bignums[i] = GetBNPtr(RARRAY_AREF(arg1, i));
+
+ points = ALLOCV_N(const EC_POINT *, tmp_p, num);
+ points[0] = point_self; /* self */
+ for (i = 0; i < num - 1; i++)
+ SafeRequire_EC_POINT(RARRAY_AREF(arg2, i), points[i + 1]);
+
+ if (argc >= 3)
+ bn_g = GetBNPtr(arg3);
+
+ if (EC_POINTs_mul(group, point_result, bn_g, num, points, bignums, ossl_bn_ctx) != 1) {
+ ALLOCV_END(tmp_b);
+ ALLOCV_END(tmp_p);
+ ossl_raise(eEC_POINT, NULL);
+ }
- if (argc >= 3) {
- bn2 = GetBNPtr(bn_v2);
- }
- if (EC_POINTs_mul(group, point2, bn2, points_len, points, bignums, ossl_bn_ctx) != 1) {
- OPENSSL_free((void *)bignums);
- OPENSSL_free((void *)points);
- ossl_raise(eEC_POINT, "Multiplication failed");
- }
- OPENSSL_free((void *)bignums);
- OPENSSL_free((void *)points);
+ ALLOCV_END(tmp_b);
+ ALLOCV_END(tmp_p);
}
- return r;
+ return result;
}
static void no_copy(VALUE klass)
@@ -1604,12 +1658,11 @@ void Init_ossl_ec(void)
ID_compressed = rb_intern("compressed");
ID_hybrid = rb_intern("hybrid");
-#ifdef OPENSSL_EC_NAMED_CURVE
rb_define_const(cEC, "NAMED_CURVE", ULONG2NUM(OPENSSL_EC_NAMED_CURVE));
-#endif
rb_define_singleton_method(cEC, "builtin_curves", ossl_s_builtin_curves, 0);
+ rb_define_singleton_method(cEC, "generate", ossl_ec_key_s_generate, 1);
rb_define_method(cEC, "initialize", ossl_ec_key_initialize, -1);
/* copy/dup/cmp */
@@ -1619,8 +1672,10 @@ void Init_ossl_ec(void)
rb_define_method(cEC, "private_key=", ossl_ec_key_set_private_key, 1);
rb_define_method(cEC, "public_key", ossl_ec_key_get_public_key, 0);
rb_define_method(cEC, "public_key=", ossl_ec_key_set_public_key, 1);
- rb_define_method(cEC, "private_key?", ossl_ec_key_is_private_key, 0);
- rb_define_method(cEC, "public_key?", ossl_ec_key_is_public_key, 0);
+ rb_define_method(cEC, "private?", ossl_ec_key_is_private, 0);
+ rb_define_method(cEC, "public?", ossl_ec_key_is_public, 0);
+ rb_define_alias(cEC, "private_key?", "private?");
+ rb_define_alias(cEC, "public_key?", "public?");
/* rb_define_method(cEC, "", ossl_ec_key_get_, 0);
rb_define_method(cEC, "=", ossl_ec_key_set_ 1);
set/get enc_flags
@@ -1628,7 +1683,8 @@ void Init_ossl_ec(void)
set/get asn1_flag (can use ruby to call self.group.asn1_flag)
set/get precompute_mult
*/
- rb_define_method(cEC, "generate_key", ossl_ec_key_generate_key, 0);
+ rb_define_method(cEC, "generate_key!", ossl_ec_key_generate_key, 0);
+ rb_define_alias(cEC, "generate_key", "generate_key!");
rb_define_method(cEC, "check_key", ossl_ec_key_check_key, 0);
rb_define_method(cEC, "dh_compute_key", ossl_ec_key_dh_compute_key, 1);
diff --git a/ext/openssl/ossl_pkey_rsa.c b/ext/openssl/ossl_pkey_rsa.c
index 20b993ab..ea2af251 100644
--- a/ext/openssl/ossl_pkey_rsa.c
+++ b/ext/openssl/ossl_pkey_rsa.c
@@ -77,7 +77,6 @@ ossl_rsa_new(EVP_PKEY *pkey)
/*
* Private
*/
-#if defined(HAVE_RSA_GENERATE_KEY_EX) && HAVE_BN_GENCB
struct rsa_blocking_gen_arg {
RSA *rsa;
BIGNUM *e;
@@ -93,12 +92,10 @@ rsa_blocking_gen(void *arg)
gen->result = RSA_generate_key_ex(gen->rsa, gen->size, gen->e, gen->cb);
return 0;
}
-#endif
static RSA *
rsa_generate(int size, unsigned long exp)
{
-#if defined(HAVE_RSA_GENERATE_KEY_EX) && HAVE_BN_GENCB
int i;
BN_GENCB cb;
struct ossl_generate_cb_arg cb_arg;
@@ -139,15 +136,16 @@ rsa_generate(int size, unsigned long exp)
if (!gen_arg.result) {
BN_free(e);
RSA_free(rsa);
- if (cb_arg.state) rb_jump_tag(cb_arg.state);
+ if (cb_arg.state) {
+ /* must clear OpenSSL error stack */
+ ossl_clear_error();
+ rb_jump_tag(cb_arg.state);
+ }
return 0;
}
BN_free(e);
return rsa;
-#else
- return RSA_generate_key(size, exp, rb_block_given_p() ? ossl_generate_cb : NULL, NULL);
-#endif
}
/*
@@ -206,7 +204,6 @@ ossl_rsa_initialize(int argc, VALUE *argv, VALUE self)
EVP_PKEY *pkey;
RSA *rsa;
BIO *in;
- char *passwd = NULL;
VALUE arg, pass;
GetPKey(self, pkey);
@@ -218,10 +215,10 @@ ossl_rsa_initialize(int argc, VALUE *argv, VALUE self)
if (!rsa) ossl_raise(eRSAError, NULL);
}
else {
- if (!NIL_P(pass)) passwd = StringValuePtr(pass);
+ pass = ossl_pem_passwd_value(pass);
arg = ossl_to_der_if_possible(arg);
in = ossl_obj2bio(arg);
- rsa = PEM_read_bio_RSAPrivateKey(in, NULL, ossl_pem_passwd_cb, passwd);
+ rsa = PEM_read_bio_RSAPrivateKey(in, NULL, ossl_pem_passwd_cb, (void *)pass);
if (!rsa) {
OSSL_BIO_reset(in);
rsa = PEM_read_bio_RSA_PUBKEY(in, NULL, NULL, NULL);
@@ -306,7 +303,6 @@ ossl_rsa_export(int argc, VALUE *argv, VALUE self)
EVP_PKEY *pkey;
BIO *out;
const EVP_CIPHER *ciph = NULL;
- char *passwd = NULL;
VALUE cipher, pass, str;
GetPKeyRSA(self, pkey);
@@ -315,19 +311,14 @@ ossl_rsa_export(int argc, VALUE *argv, VALUE self)
if (!NIL_P(cipher)) {
ciph = GetCipherPtr(cipher);
- if (!NIL_P(pass)) {
- StringValue(pass);
- if (RSTRING_LENINT(pass) < OSSL_MIN_PWD_LEN)
- ossl_raise(eOSSLError, "OpenSSL requires passwords to be at least four characters long");
- passwd = RSTRING_PTR(pass);
- }
+ pass = ossl_pem_passwd_value(pass);
}
if (!(out = BIO_new(BIO_s_mem()))) {
ossl_raise(eRSAError, NULL);
}
if (RSA_HAS_PRIVATE(pkey->pkey.rsa)) {
if (!PEM_write_bio_RSAPrivateKey(out, pkey->pkey.rsa, ciph,
- NULL, 0, ossl_pem_passwd_cb, passwd)) {
+ NULL, 0, ossl_pem_passwd_cb, (void *)pass)) {
BIO_free(out);
ossl_raise(eRSAError, NULL);
}
@@ -391,6 +382,8 @@ ossl_rsa_public_encrypt(int argc, VALUE *argv, VALUE self)
VALUE str, buffer, padding;
GetPKeyRSA(self, pkey);
+ if (!pkey->pkey.rsa->n)
+ ossl_raise(eRSAError, "incomplete RSA");
rb_scan_args(argc, argv, "11", &buffer, &padding);
pad = (argc == 1) ? RSA_PKCS1_PADDING : NUM2INT(padding);
StringValue(buffer);
@@ -420,6 +413,8 @@ ossl_rsa_public_decrypt(int argc, VALUE *argv, VALUE self)
VALUE str, buffer, padding;
GetPKeyRSA(self, pkey);
+ if (!pkey->pkey.rsa->n)
+ ossl_raise(eRSAError, "incomplete RSA");
rb_scan_args(argc, argv, "11", &buffer, &padding);
pad = (argc == 1) ? RSA_PKCS1_PADDING : NUM2INT(padding);
StringValue(buffer);
@@ -449,9 +444,10 @@ ossl_rsa_private_encrypt(int argc, VALUE *argv, VALUE self)
VALUE str, buffer, padding;
GetPKeyRSA(self, pkey);
- if (!RSA_PRIVATE(self, pkey->pkey.rsa)) {
- ossl_raise(eRSAError, "private key needed.");
- }
+ if (!pkey->pkey.rsa->n)
+ ossl_raise(eRSAError, "incomplete RSA");
+ if (!RSA_PRIVATE(self, pkey->pkey.rsa))
+ ossl_raise(eRSAError, "private key needed");
rb_scan_args(argc, argv, "11", &buffer, &padding);
pad = (argc == 1) ? RSA_PKCS1_PADDING : NUM2INT(padding);
StringValue(buffer);
@@ -481,9 +477,10 @@ ossl_rsa_private_decrypt(int argc, VALUE *argv, VALUE self)
VALUE str, buffer, padding;
GetPKeyRSA(self, pkey);
- if (!RSA_PRIVATE(self, pkey->pkey.rsa)) {
- ossl_raise(eRSAError, "private key needed.");
- }
+ if (!pkey->pkey.rsa->n)
+ ossl_raise(eRSAError, "incomplete RSA");
+ if (!RSA_PRIVATE(self, pkey->pkey.rsa))
+ ossl_raise(eRSAError, "private key needed");
rb_scan_args(argc, argv, "11", &buffer, &padding);
pad = (argc == 1) ? RSA_PKCS1_PADDING : NUM2INT(padding);
StringValue(buffer);
diff --git a/ext/openssl/ossl_rand.c b/ext/openssl/ossl_rand.c
index daf866d7..3a300d5e 100644
--- a/ext/openssl/ossl_rand.c
+++ b/ext/openssl/ossl_rand.c
@@ -67,9 +67,9 @@ ossl_rand_add(VALUE self, VALUE str, VALUE entropy)
static VALUE
ossl_rand_load_file(VALUE self, VALUE filename)
{
- SafeStringValue(filename);
+ rb_check_safe_obj(filename);
- if(!RAND_load_file(RSTRING_PTR(filename), -1)) {
+ if(!RAND_load_file(StringValueCStr(filename), -1)) {
ossl_raise(eRandomError, NULL);
}
return Qtrue;
@@ -86,8 +86,9 @@ ossl_rand_load_file(VALUE self, VALUE filename)
static VALUE
ossl_rand_write_file(VALUE self, VALUE filename)
{
- SafeStringValue(filename);
- if (RAND_write_file(RSTRING_PTR(filename)) == -1) {
+ rb_check_safe_obj(filename);
+
+ if (RAND_write_file(StringValueCStr(filename)) == -1) {
ossl_raise(eRandomError, NULL);
}
return Qtrue;
@@ -114,10 +115,8 @@ ossl_rand_bytes(VALUE self, VALUE len)
str = rb_str_new(0, n);
ret = RAND_bytes((unsigned char *)RSTRING_PTR(str), n);
- if (ret == 0){
- char buf[256];
- ERR_error_string_n(ERR_get_error(), buf, 256);
- ossl_raise(eRandomError, "RAND_bytes error: %s", buf);
+ if (ret == 0) {
+ ossl_raise(eRandomError, "RAND_bytes");
} else if (ret == -1) {
ossl_raise(eRandomError, "RAND_bytes is not supported");
}
@@ -146,7 +145,7 @@ ossl_rand_pseudo_bytes(VALUE self, VALUE len)
int n = NUM2INT(len);
str = rb_str_new(0, n);
- if (!RAND_pseudo_bytes((unsigned char *)RSTRING_PTR(str), n)) {
+ if (RAND_pseudo_bytes((unsigned char *)RSTRING_PTR(str), n) < 1) {
ossl_raise(eRandomError, NULL);
}
@@ -163,9 +162,9 @@ ossl_rand_pseudo_bytes(VALUE self, VALUE len)
static VALUE
ossl_rand_egd(VALUE self, VALUE filename)
{
- SafeStringValue(filename);
+ rb_check_safe_obj(filename);
- if(!RAND_egd(RSTRING_PTR(filename))) {
+ if (RAND_egd(StringValueCStr(filename)) == -1) {
ossl_raise(eRandomError, NULL);
}
return Qtrue;
@@ -185,9 +184,9 @@ ossl_rand_egd_bytes(VALUE self, VALUE filename, VALUE len)
{
int n = NUM2INT(len);
- SafeStringValue(filename);
+ rb_check_safe_obj(filename);
- if (!RAND_egd_bytes(RSTRING_PTR(filename), n)) {
+ if (RAND_egd_bytes(StringValueCStr(filename), n) == -1) {
ossl_raise(eRandomError, NULL);
}
return Qtrue;
diff --git a/ext/openssl/ossl_ssl.c b/ext/openssl/ossl_ssl.c
index 4075d6f0..0f5313bd 100644
--- a/ext/openssl/ossl_ssl.c
+++ b/ext/openssl/ossl_ssl.c
@@ -70,6 +70,10 @@ static VALUE eSSLErrorWaitWritable;
#define ossl_ssl_get_x509(o) rb_iv_get((o),"@x509")
#define ossl_ssl_get_key(o) rb_iv_get((o),"@key")
+#define ossl_ssl_set_io(o,v) rb_iv_set((o),"@io",(v))
+#define ossl_ssl_set_ctx(o,v) rb_iv_set((o),"@context",(v))
+#define ossl_ssl_set_sync_close(o,v) rb_iv_set((o),"@sync_close",(v))
+#define ossl_ssl_set_hostname_v(o,v) rb_iv_set((o),"@hostname",(v))
#define ossl_ssl_set_x509(o,v) rb_iv_set((o),"@x509",(v))
#define ossl_ssl_set_key(o,v) rb_iv_set((o),"@key",(v))
#define ossl_ssl_set_tmp_dh(o,v) rb_iv_set((o),"@tmp_dh",(v))
@@ -90,26 +94,22 @@ static const struct {
OSSL_SSL_METHOD_ENTRY(TLSv1),
OSSL_SSL_METHOD_ENTRY(TLSv1_server),
OSSL_SSL_METHOD_ENTRY(TLSv1_client),
-#if defined(HAVE_TLSV1_2_METHOD) && defined(HAVE_TLSV1_2_SERVER_METHOD) && \
- defined(HAVE_TLSV1_2_CLIENT_METHOD)
+#if defined(HAVE_TLSV1_2_METHOD)
OSSL_SSL_METHOD_ENTRY(TLSv1_2),
OSSL_SSL_METHOD_ENTRY(TLSv1_2_server),
OSSL_SSL_METHOD_ENTRY(TLSv1_2_client),
#endif
-#if defined(HAVE_TLSV1_1_METHOD) && defined(HAVE_TLSV1_1_SERVER_METHOD) && \
- defined(HAVE_TLSV1_1_CLIENT_METHOD)
+#if defined(HAVE_TLSV1_1_METHOD)
OSSL_SSL_METHOD_ENTRY(TLSv1_1),
OSSL_SSL_METHOD_ENTRY(TLSv1_1_server),
OSSL_SSL_METHOD_ENTRY(TLSv1_1_client),
#endif
-#if defined(HAVE_SSLV2_METHOD) && defined(HAVE_SSLV2_SERVER_METHOD) && \
- defined(HAVE_SSLV2_CLIENT_METHOD)
+#if defined(HAVE_SSLV2_METHOD)
OSSL_SSL_METHOD_ENTRY(SSLv2),
OSSL_SSL_METHOD_ENTRY(SSLv2_server),
OSSL_SSL_METHOD_ENTRY(SSLv2_client),
#endif
-#if defined(HAVE_SSLV3_METHOD) && defined(HAVE_SSLV3_SERVER_METHOD) && \
- defined(HAVE_SSLV3_CLIENT_METHOD)
+#if defined(HAVE_SSLV3_METHOD)
OSSL_SSL_METHOD_ENTRY(SSLv3),
OSSL_SSL_METHOD_ENTRY(SSLv3_server),
OSSL_SSL_METHOD_ENTRY(SSLv3_client),
@@ -145,7 +145,8 @@ static VALUE
ossl_sslctx_s_alloc(VALUE klass)
{
SSL_CTX *ctx;
- long mode = SSL_MODE_ENABLE_PARTIAL_WRITE;
+ long mode = SSL_MODE_ENABLE_PARTIAL_WRITE |
+ SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER;
VALUE obj;
#ifdef SSL_MODE_RELEASE_BUFFERS
@@ -161,6 +162,18 @@ ossl_sslctx_s_alloc(VALUE klass)
RTYPEDDATA_DATA(obj) = ctx;
SSL_CTX_set_ex_data(ctx, ossl_ssl_ex_ptr_idx, (void*)obj);
+#if defined(HAVE_SSL_CTX_SET_ECDH_AUTO)
+ /* We use SSL_CTX_set1_curves_list() to specify the curve used in ECDH. It
+ * allows to specify multiple curve names and OpenSSL will select
+ * automatically from them. In OpenSSL 1.0.2, the automatic selection has to
+ * be enabled explicitly. But OpenSSL 1.1.0 removed the knob and it is
+ * always enabled. To uniform the behavior, we enable the automatic
+ * selection also in 1.0.2. Users can still disable ECDH by removing ECDH
+ * cipher suites by SSLContext#ciphers=. */
+ if (!SSL_CTX_set_ecdh_auto(ctx, 1))
+ ossl_raise(eSSLError, "SSL_CTX_set_ecdh_auto");
+#endif
+
return obj;
}
@@ -307,7 +320,7 @@ ossl_ssl_verify_callback(int preverify_ok, X509_STORE_CTX *ctx)
ssl = X509_STORE_CTX_get_ex_data(ctx, SSL_get_ex_data_X509_STORE_CTX_idx());
cb = (VALUE)SSL_get_ex_data(ssl, ossl_ssl_ex_vcb_idx);
- X509_STORE_CTX_set_ex_data(ctx, ossl_verify_cb_idx, (void*)cb);
+ X509_STORE_CTX_set_ex_data(ctx, ossl_store_ctx_ex_verify_cb_idx, (void *)cb);
return ossl_verify_cb(preverify_ok, ctx);
}
@@ -544,7 +557,7 @@ ssl_renegotiation_cb(const SSL *ssl)
(void) rb_funcall(cb, rb_intern("call"), 1, ssl_obj);
}
-#ifdef HAVE_OPENSSL_NPN_NEGOTIATED
+#if defined(HAVE_SSL_CTX_SET_NEXT_PROTO_SELECT_CB) || defined(HAVE_SSL_CTX_SET_ALPN_SELECT_CB)
static VALUE
ssl_npn_encode_protocol_i(VALUE cur, VALUE encoded)
{
@@ -562,25 +575,12 @@ ssl_npn_encode_protocol_i(VALUE cur, VALUE encoded)
static VALUE
ssl_encode_npn_protocols(VALUE protocols)
{
- VALUE encoded = rb_str_new2("");
+ VALUE encoded = rb_str_new(NULL, 0);
rb_iterate(rb_each, protocols, ssl_npn_encode_protocol_i, encoded);
- StringValueCStr(encoded);
return encoded;
}
static int
-ssl_npn_advertise_cb(SSL *ssl, const unsigned char **out, unsigned int *outlen, void *arg)
-{
- VALUE sslctx_obj = (VALUE) arg;
- VALUE protocols = rb_iv_get(sslctx_obj, "@_protocols");
-
- *out = (const unsigned char *) RSTRING_PTR(protocols);
- *outlen = RSTRING_LENINT(protocols);
-
- return SSL_TLSEXT_ERR_OK;
-}
-
-static int
ssl_npn_select_cb_common(VALUE cb, const unsigned char **out, unsigned char *outlen, const unsigned char *in, unsigned int inlen)
{
VALUE selected;
@@ -609,6 +609,19 @@ ssl_npn_select_cb_common(VALUE cb, const unsigned char **out, unsigned char *out
return SSL_TLSEXT_ERR_OK;
}
+#ifdef HAVE_SSL_CTX_SET_NEXT_PROTO_SELECT_CB
+static int
+ssl_npn_advertise_cb(SSL *ssl, const unsigned char **out, unsigned int *outlen, void *arg)
+{
+ VALUE sslctx_obj = (VALUE) arg;
+ VALUE protocols = rb_iv_get(sslctx_obj, "@_protocols");
+
+ *out = (const unsigned char *) RSTRING_PTR(protocols);
+ *outlen = RSTRING_LENINT(protocols);
+
+ return SSL_TLSEXT_ERR_OK;
+}
+
static int
ssl_npn_select_cb(SSL *s, unsigned char **out, unsigned char *outlen, const unsigned char *in, unsigned int inlen, void *arg)
{
@@ -619,6 +632,7 @@ ssl_npn_select_cb(SSL *s, unsigned char **out, unsigned char *outlen, const unsi
return ssl_npn_select_cb_common(cb, (const unsigned char **)out, outlen, in, inlen);
}
+#endif
#ifdef HAVE_SSL_CTX_SET_ALPN_SELECT_CB
static int
@@ -632,8 +646,7 @@ ssl_alpn_select_cb(SSL *ssl, const unsigned char **out, unsigned char *outlen, c
return ssl_npn_select_cb_common(cb, out, outlen, in, inlen);
}
#endif
-
-#endif
+#endif /* HAVE_SSL_CTX_SET_NEXT_PROTO_SELECT_CB || HAVE_SSL_CTX_SET_ALPN_SELECT_CB */
/* This function may serve as the entry point to support further
* callbacks. */
@@ -687,8 +700,8 @@ ossl_sslctx_set_options(VALUE self, VALUE options)
* ctx.setup => nil # thereafter
*
* This method is called automatically when a new SSLSocket is created.
- * Normally you do not need to call this method (unless you are writing an
- * extension in C).
+ * However, it is not thread-safe and must be called before creating
+ * SSLSocket objects in a multi-threaded program.
*/
static VALUE
ossl_sslctx_setup(VALUE self)
@@ -710,10 +723,24 @@ ossl_sslctx_setup(VALUE self)
#endif
#if !defined(OPENSSL_NO_EC)
- if (RTEST(ossl_sslctx_get_tmp_ecdh_cb(self))){
+ /* We added SSLContext#tmp_ecdh_callback= in Ruby 2.3.0,
+ * but SSL_CTX_set_tmp_ecdh_callback() was removed in OpenSSL 1.1.0. */
+ if (RTEST(ossl_sslctx_get_tmp_ecdh_cb(self))) {
+# if defined(HAVE_SSL_CTX_SET_TMP_ECDH_CALLBACK)
+ rb_warn("#tmp_ecdh_callback= is deprecated; use #ecdh_curves= instead");
SSL_CTX_set_tmp_ecdh_callback(ctx, ossl_tmp_ecdh_callback);
+# if defined(HAVE_SSL_CTX_SET_ECDH_AUTO)
+ /* tmp_ecdh_callback and ecdh_auto conflict; OpenSSL ignores
+ * tmp_ecdh_callback. So disable ecdh_auto. */
+ if (!SSL_CTX_set_ecdh_auto(ctx, 0))
+ ossl_raise(eSSLError, "SSL_CTX_set_ecdh_auto");
+# endif
+# else
+ ossl_raise(eSSLError, "OpenSSL does not support tmp_ecdh_callback; "
+ "use #ecdh_curves= instead");
+# endif
}
-#endif
+#endif /* OPENSSL_NO_EC */
val = ossl_sslctx_get_cert_store(self);
if(!NIL_P(val)){
@@ -773,9 +800,9 @@ ossl_sslctx_setup(VALUE self)
}
val = ossl_sslctx_get_ca_file(self);
- ca_file = NIL_P(val) ? NULL : StringValuePtr(val);
+ ca_file = NIL_P(val) ? NULL : StringValueCStr(val);
val = ossl_sslctx_get_ca_path(self);
- ca_path = NIL_P(val) ? NULL : StringValuePtr(val);
+ ca_path = NIL_P(val) ? NULL : StringValueCStr(val);
if(ca_file || ca_path){
if (!SSL_CTX_load_verify_locations(ctx, ca_file, ca_path))
rb_warning("can't set verify locations");
@@ -793,7 +820,7 @@ ossl_sslctx_setup(VALUE self)
val = ossl_sslctx_get_verify_dep(self);
if(!NIL_P(val)) SSL_CTX_set_verify_depth(ctx, NUM2INT(val));
-#ifdef HAVE_OPENSSL_NPN_NEGOTIATED
+#ifdef HAVE_SSL_CTX_SET_NEXT_PROTO_SELECT_CB
val = rb_iv_get(self, "@npn_protocols");
if (!NIL_P(val)) {
rb_iv_set(self, "@_protocols", ssl_encode_npn_protocols(val));
@@ -810,7 +837,7 @@ ossl_sslctx_setup(VALUE self)
val = rb_iv_get(self, "@alpn_protocols");
if (!NIL_P(val)) {
VALUE rprotos = ssl_encode_npn_protocols(val);
- SSL_CTX_set_alpn_protos(ctx, (const unsigned char *)StringValueCStr(rprotos), RSTRING_LENINT(rprotos));
+ SSL_CTX_set_alpn_protos(ctx, (unsigned char *)RSTRING_PTR(rprotos), RSTRING_LENINT(rprotos));
OSSL_Debug("SSL ALPN values added");
}
if (RTEST(rb_iv_get(self, "@alpn_select_cb"))) {
@@ -945,13 +972,94 @@ ossl_sslctx_set_ciphers(VALUE self, VALUE v)
ossl_raise(eSSLError, "SSL_CTX is not initialized.");
return Qnil;
}
- if (!SSL_CTX_set_cipher_list(ctx, RSTRING_PTR(str))) {
+ if (!SSL_CTX_set_cipher_list(ctx, StringValueCStr(str))) {
ossl_raise(eSSLError, "SSL_CTX_set_cipher_list");
}
return v;
}
+#if !defined(OPENSSL_NO_EC)
+/*
+ * call-seq:
+ * ctx.ecdh_curves = curve_list -> curve_list
+ *
+ * Sets the list of "supported elliptic curves" for this context.
+ *
+ * For a TLS client, the list is directly used in the Supported Elliptic Curves
+ * Extension. For a server, the list is used by OpenSSL to determine the set of
+ * shared curves. OpenSSL will pick the most appropriate one from it.
+ *
+ * Note that this works differently with old OpenSSL (<= 1.0.1). Only one curve
+ * can be set, and this has no effect for TLS clients.
+ *
+ * === Example
+ * ctx1 = OpenSSL::SSL::SSLContext.new
+ * ctx1.ecdh_curves = "X25519:P-256:P-224"
+ * svr = OpenSSL::SSL::SSLServer.new(tcp_svr, ctx1)
+ * Thread.new { svr.accept }
+ *
+ * ctx2 = OpenSSL::SSL::SSLContext.new
+ * ctx2.ecdh_curves = "P-256"
+ * cli = OpenSSL::SSL::SSLSocket.new(tcp_sock, ctx2)
+ * cli.connect
+ *
+ * p cli.tmp_key.group.curve_name
+ * # => "prime256v1" (is an alias for NIST P-256)
+ */
+static VALUE
+ossl_sslctx_set_ecdh_curves(VALUE self, VALUE arg)
+{
+ SSL_CTX *ctx;
+
+ rb_check_frozen(self);
+ GetSSLCTX(self, ctx);
+ StringValueCStr(arg);
+
+#if defined(HAVE_SSL_CTX_SET1_CURVES_LIST)
+ if (!SSL_CTX_set1_curves_list(ctx, RSTRING_PTR(arg)))
+ ossl_raise(eSSLError, NULL);
+#else
+ /* OpenSSL does not have SSL_CTX_set1_curves_list()... Fallback to
+ * SSL_CTX_set_tmp_ecdh(). So only the first curve is used. */
+ {
+ VALUE curve, splitted;
+ EC_KEY *ec;
+ int nid;
+
+ splitted = rb_str_split(arg, ":");
+ if (!RARRAY_LEN(splitted))
+ ossl_raise(eSSLError, "invalid input format");
+ curve = RARRAY_AREF(splitted, 0);
+ StringValueCStr(curve);
+
+ /* SSL_CTX_set1_curves_list() accepts NIST names */
+ nid = EC_curve_nist2nid(RSTRING_PTR(curve));
+ if (nid == NID_undef)
+ nid = OBJ_txt2nid(RSTRING_PTR(curve));
+ if (nid == NID_undef)
+ ossl_raise(eSSLError, "unknown curve name");
+
+ ec = EC_KEY_new_by_curve_name(nid);
+ if (!ec)
+ ossl_raise(eSSLError, NULL);
+ EC_KEY_set_asn1_flag(ec, OPENSSL_EC_NAMED_CURVE);
+ SSL_CTX_set_tmp_ecdh(ctx, ec);
+# if defined(HAVE_SSL_CTX_SET_ECDH_AUTO)
+ /* tmp_ecdh and ecdh_auto conflict. tmp_ecdh is ignored when ecdh_auto
+ * is enabled. So disable ecdh_auto. */
+ if (!SSL_CTX_set_ecdh_auto(ctx, 0))
+ ossl_raise(eSSLError, "SSL_CTX_set_ecdh_auto");
+# endif
+ }
+#endif
+
+ return arg;
+}
+#else
+#define ossl_sslctx_set_ecdh_curves rb_f_notimplement
+#endif
+
/*
* call-seq:
* ctx.session_add(session) -> true | false
@@ -1142,25 +1250,29 @@ ossl_sslctx_flush_sessions(int argc, VALUE *argv, VALUE self)
* SSLSocket class
*/
#ifndef OPENSSL_NO_SOCK
+static inline int
+ssl_started(SSL *ssl)
+{
+ /* the FD is set in ossl_ssl_setup(), called by #connect or #accept */
+ return SSL_get_fd(ssl) >= 0;
+}
+
static void
ossl_ssl_shutdown(SSL *ssl)
{
- int i, rc;
-
- if (ssl) {
- /* 4 is from SSL_smart_shutdown() of mod_ssl.c (v2.2.19) */
- /* It says max 2x pending + 2x data = 4 */
- for (i = 0; i < 4; ++i) {
- /*
- * Ignore the case SSL_shutdown returns -1. Empty handshake_func
- * must not happen.
- */
- if ((rc = SSL_shutdown(ssl)) != 0)
- break;
- }
- SSL_clear(ssl);
- ERR_clear_error();
+ int i;
+
+ /* 4 is from SSL_smart_shutdown() of mod_ssl.c (v2.2.19) */
+ /* It says max 2x pending + 2x data = 4 */
+ for (i = 0; i < 4; ++i) {
+ /*
+ * Ignore the case SSL_shutdown returns -1. Empty handshake_func
+ * must not happen.
+ */
+ if (SSL_shutdown(ssl) != 0)
+ break;
}
+ ossl_clear_error();
}
static void
@@ -1183,45 +1295,77 @@ ossl_ssl_s_alloc(VALUE klass)
return TypedData_Wrap_Struct(klass, &ossl_ssl_type, NULL);
}
+/*
+ * call-seq:
+ * SSLSocket.new(io) => aSSLSocket
+ * SSLSocket.new(io, ctx) => aSSLSocket
+ *
+ * Creates a new SSL socket from +io+ which must be a real ruby object (not an
+ * IO-like object that responds to read/write).
+ *
+ * If +ctx+ is provided the SSL Sockets initial params will be taken from
+ * the context.
+ *
+ * The OpenSSL::Buffering module provides additional IO methods.
+ *
+ * This method will freeze the SSLContext if one is provided;
+ * however, session management is still allowed in the frozen SSLContext.
+ */
static VALUE
-ossl_ssl_setup(VALUE self)
+ossl_ssl_initialize(int argc, VALUE *argv, VALUE self)
{
- VALUE io, v_ctx, cb;
+ VALUE io, v_ctx, verify_cb;
+ SSL *ssl;
SSL_CTX *ctx;
+
+ TypedData_Get_Struct(self, SSL, &ossl_ssl_type, ssl);
+ if (ssl)
+ ossl_raise(eSSLError, "SSL already initialized");
+
+ if (rb_scan_args(argc, argv, "11", &io, &v_ctx) == 1)
+ v_ctx = rb_funcall(cSSLContext, rb_intern("new"), 0);
+
+ GetSSLCTX(v_ctx, ctx);
+ ossl_ssl_set_ctx(self, v_ctx);
+ ossl_sslctx_setup(v_ctx);
+
+ if (rb_respond_to(io, rb_intern("nonblock=")))
+ rb_funcall(io, rb_intern("nonblock="), 1, Qtrue);
+ ossl_ssl_set_io(self, io);
+
+ ossl_ssl_set_sync_close(self, Qfalse);
+
+ ssl = SSL_new(ctx);
+ if (!ssl)
+ ossl_raise(eSSLError, NULL);
+ RTYPEDDATA_DATA(self) = ssl;
+
+ SSL_set_ex_data(ssl, ossl_ssl_ex_ptr_idx, (void *)self);
+ SSL_set_info_callback(ssl, ssl_info_cb);
+ verify_cb = ossl_sslctx_get_verify_cb(v_ctx);
+ SSL_set_ex_data(ssl, ossl_ssl_ex_vcb_idx, (void *)verify_cb);
+
+ rb_call_super(0, NULL);
+
+ return self;
+}
+
+static VALUE
+ossl_ssl_setup(VALUE self)
+{
+ VALUE io;
SSL *ssl;
rb_io_t *fptr;
GetSSL(self, ssl);
- if(!ssl){
-#ifdef HAVE_SSL_SET_TLSEXT_HOST_NAME
- VALUE hostname = rb_iv_get(self, "@hostname");
-#endif
-
- v_ctx = ossl_ssl_get_ctx(self);
- GetSSLCTX(v_ctx, ctx);
-
- ssl = SSL_new(ctx);
- if (!ssl) {
- ossl_raise(eSSLError, "SSL_new");
- }
- DATA_PTR(self) = ssl;
+ if (ssl_started(ssl))
+ return Qtrue;
-#ifdef HAVE_SSL_SET_TLSEXT_HOST_NAME
- if (!NIL_P(hostname)) {
- if (SSL_set_tlsext_host_name(ssl, StringValuePtr(hostname)) != 1)
- ossl_raise(eSSLError, "SSL_set_tlsext_host_name");
- }
-#endif
- io = ossl_ssl_get_io(self);
- GetOpenFile(io, fptr);
- rb_io_check_readable(fptr);
- rb_io_check_writable(fptr);
- SSL_set_fd(ssl, TO_SOCKET(FPTR_TO_FD(fptr)));
- SSL_set_ex_data(ssl, ossl_ssl_ex_ptr_idx, (void*)self);
- cb = ossl_sslctx_get_verify_cb(v_ctx);
- SSL_set_ex_data(ssl, ossl_ssl_ex_vcb_idx, (void*)cb);
- SSL_set_info_callback(ssl, ssl_info_cb);
- }
+ io = ossl_ssl_get_io(self);
+ GetOpenFile(io, fptr);
+ rb_io_check_readable(fptr);
+ rb_io_check_writable(fptr);
+ SSL_set_fd(ssl, TO_SOCKET(FPTR_TO_FD(fptr)));
return Qtrue;
}
@@ -1232,15 +1376,6 @@ ossl_ssl_setup(VALUE self)
#define ssl_get_error(ssl, ret) SSL_get_error((ssl), (ret))
#endif
-#define ossl_ssl_data_get_struct(v, ssl) \
-do { \
- GetSSL((v), (ssl)); \
- if (!(ssl)) { \
- rb_warning("SSL session is not started yet."); \
- return Qnil; \
- } \
-} while (0)
-
static void
write_would_block(int nonblock)
{
@@ -1279,15 +1414,18 @@ ossl_start_ssl(VALUE self, int (*func)(), const char *funcname, VALUE opts)
rb_ivar_set(self, ID_callback_state, Qnil);
- ossl_ssl_data_get_struct(self, ssl);
+ GetSSL(self, ssl);
GetOpenFile(ossl_ssl_get_io(self), fptr);
for(;;){
ret = func(ssl);
cb_state = rb_ivar_get(self, ID_callback_state);
- if (!NIL_P(cb_state))
- rb_jump_tag(NUM2INT(cb_state));
+ if (!NIL_P(cb_state)) {
+ /* must cleanup OpenSSL error stack before re-raising */
+ ossl_clear_error();
+ rb_jump_tag(NUM2INT(cb_state));
+ }
if (ret > 0)
break;
@@ -1436,7 +1574,7 @@ ossl_ssl_read_internal(int argc, VALUE *argv, VALUE self, int nonblock)
GetSSL(self, ssl);
GetOpenFile(ossl_ssl_get_io(self), fptr);
- if (ssl) {
+ if (ssl_started(ssl)) {
if(!nonblock && SSL_pending(ssl) <= 0)
rb_thread_wait_fd(FPTR_TO_FD(fptr));
for (;;){
@@ -1530,7 +1668,7 @@ ossl_ssl_write_internal(VALUE self, VALUE str, VALUE opts)
GetSSL(self, ssl);
GetOpenFile(ossl_ssl_get_io(self), fptr);
- if (ssl) {
+ if (ssl_started(ssl)) {
for (;;){
nwrite = SSL_write(ssl, RSTRING_PTR(str), RSTRING_LENINT(str));
switch(ssl_get_error(ssl, nwrite)){
@@ -1596,23 +1734,17 @@ ossl_ssl_write_nonblock(int argc, VALUE *argv, VALUE self)
* call-seq:
* ssl.stop => nil
*
- * Stops the SSL connection and prepares it for another connection.
+ * Sends "close notify" to the peer and tries to shut down the SSL connection
+ * gracefully.
*/
static VALUE
ossl_ssl_stop(VALUE self)
{
SSL *ssl;
- /* ossl_ssl_data_get_struct() is not usable here because it may return
- * from this function; */
-
GetSSL(self, ssl);
- if (ssl) {
- ossl_ssl_shutdown(ssl);
- SSL_free(ssl);
- }
- DATA_PTR(self) = NULL;
+ ossl_ssl_shutdown(ssl);
return Qnil;
}
@@ -1629,7 +1761,7 @@ ossl_ssl_get_cert(VALUE self)
SSL *ssl;
X509 *cert = NULL;
- ossl_ssl_data_get_struct(self, ssl);
+ GetSSL(self, ssl);
/*
* Is this OpenSSL bug? Should add a ref?
@@ -1656,7 +1788,7 @@ ossl_ssl_get_peer_cert(VALUE self)
X509 *cert = NULL;
VALUE obj;
- ossl_ssl_data_get_struct(self, ssl);
+ GetSSL(self, ssl);
cert = SSL_get_peer_certificate(ssl); /* Adds a ref => Safe to FREE. */
@@ -1684,7 +1816,7 @@ ossl_ssl_get_peer_cert_chain(VALUE self)
VALUE ary;
int i, num;
- ossl_ssl_data_get_struct(self, ssl);
+ GetSSL(self, ssl);
chain = SSL_get_peer_cert_chain(ssl);
if(!chain) return Qnil;
@@ -1710,7 +1842,7 @@ ossl_ssl_get_version(VALUE self)
{
SSL *ssl;
- ossl_ssl_data_get_struct(self, ssl);
+ GetSSL(self, ssl);
return rb_str_new2(SSL_get_version(ssl));
}
@@ -1727,7 +1859,7 @@ ossl_ssl_get_cipher(VALUE self)
SSL *ssl;
SSL_CIPHER *cipher;
- ossl_ssl_data_get_struct(self, ssl);
+ GetSSL(self, ssl);
cipher = (SSL_CIPHER *)SSL_get_current_cipher(ssl);
@@ -1746,7 +1878,7 @@ ossl_ssl_get_state(VALUE self)
SSL *ssl;
VALUE ret;
- ossl_ssl_data_get_struct(self, ssl);
+ GetSSL(self, ssl);
ret = rb_str_new2(SSL_state_string(ssl));
if (ruby_verbose) {
@@ -1767,7 +1899,7 @@ ossl_ssl_pending(VALUE self)
{
SSL *ssl;
- ossl_ssl_data_get_struct(self, ssl);
+ GetSSL(self, ssl);
return INT2NUM(SSL_pending(ssl));
}
@@ -1783,15 +1915,9 @@ ossl_ssl_session_reused(VALUE self)
{
SSL *ssl;
- ossl_ssl_data_get_struct(self, ssl);
-
- switch(SSL_session_reused(ssl)) {
- case 1: return Qtrue;
- case 0: return Qfalse;
- default: ossl_raise(eSSLError, "SSL_session_reused");
- }
+ GetSSL(self, ssl);
- UNREACHABLE;
+ return SSL_session_reused(ssl) ? Qtrue : Qfalse;
}
/*
@@ -1806,11 +1932,7 @@ ossl_ssl_set_session(VALUE self, VALUE arg1)
SSL *ssl;
SSL_SESSION *sess;
-/* why is ossl_ssl_setup delayed? */
- ossl_ssl_setup(self);
-
- ossl_ssl_data_get_struct(self, ssl);
-
+ GetSSL(self, ssl);
SafeGetSSLSession(arg1, sess);
if (SSL_set_session(ssl, sess) != 1)
@@ -1821,6 +1943,35 @@ ossl_ssl_set_session(VALUE self, VALUE arg1)
/*
* call-seq:
+ * ssl.hostname = hostname -> hostname
+ *
+ * Sets the server hostname used for SNI. This needs to be set before
+ * SSLSocket#connect.
+ */
+#ifdef HAVE_SSL_SET_TLSEXT_HOST_NAME
+static VALUE
+ossl_ssl_set_hostname(VALUE self, VALUE arg)
+{
+ SSL *ssl;
+ char *hostname = NULL;
+
+ GetSSL(self, ssl);
+
+ if (!NIL_P(arg))
+ hostname = StringValueCStr(arg);
+
+ if (!SSL_set_tlsext_host_name(ssl, hostname))
+ ossl_raise(eSSLError, NULL);
+
+ /* for SSLSocket#hostname */
+ ossl_ssl_set_hostname_v(self, arg);
+
+ return arg;
+}
+#endif
+
+/*
+ * call-seq:
* ssl.verify_result => Integer
*
* Returns the result of the peer certificates verification. See verify(1)
@@ -1833,7 +1984,7 @@ ossl_ssl_get_verify_result(VALUE self)
{
SSL *ssl;
- ossl_ssl_data_get_struct(self, ssl);
+ GetSSL(self, ssl);
return INT2FIX(SSL_get_verify_result(ssl));
}
@@ -1855,13 +2006,13 @@ ossl_ssl_get_client_ca_list(VALUE self)
SSL *ssl;
STACK_OF(X509_NAME) *ca;
- ossl_ssl_data_get_struct(self, ssl);
+ GetSSL(self, ssl);
ca = SSL_get_client_CA_list(ssl);
return ossl_x509name_sk2ary(ca);
}
-# ifdef HAVE_OPENSSL_NPN_NEGOTIATED
+# ifdef HAVE_SSL_CTX_SET_NEXT_PROTO_SELECT_CB
/*
* call-seq:
* ssl.npn_protocol => String
@@ -1876,7 +2027,7 @@ ossl_ssl_npn_protocol(VALUE self)
const unsigned char *out;
unsigned int outlen;
- ossl_ssl_data_get_struct(self, ssl);
+ GetSSL(self, ssl);
SSL_get0_next_proto_negotiated(ssl, &out, &outlen);
if (!outlen)
@@ -1901,7 +2052,7 @@ ossl_ssl_alpn_protocol(VALUE self)
const unsigned char *out;
unsigned int outlen;
- ossl_ssl_data_get_struct(self, ssl);
+ GetSSL(self, ssl);
SSL_get0_alpn_selected(ssl, &out, &outlen);
if (!outlen)
@@ -1910,6 +2061,26 @@ ossl_ssl_alpn_protocol(VALUE self)
return rb_str_new((const char *) out, outlen);
}
# endif
+
+# ifdef HAVE_SSL_GET_SERVER_TMP_KEY
+/*
+ * call-seq:
+ * ssl.tmp_key => PKey or nil
+ *
+ * Returns the ephemeral key used in case of forward secrecy cipher
+ */
+static VALUE
+ossl_ssl_tmp_key(VALUE self)
+{
+ SSL *ssl;
+ EVP_PKEY *key;
+
+ GetSSL(self, ssl);
+ if (!SSL_get_server_tmp_key(ssl, &key))
+ return Qnil;
+ return ossl_pkey_new(key);
+}
+# endif /* defined(HAVE_SSL_GET_SERVER_TMP_KEY) */
#endif /* !defined(OPENSSL_NO_SOCK) */
void
@@ -2055,6 +2226,7 @@ Init_ossl_ssl(void)
*/
rb_attr(cSSLContext, rb_intern("client_cert_cb"), 1, 1, Qfalse);
+#if defined(HAVE_SSL_CTX_SET_TMP_ECDH_CALLBACK)
/*
* A callback invoked when ECDH parameters are required.
*
@@ -2062,10 +2234,11 @@ Init_ossl_ssl(void)
* flag indicating the use of an export cipher and the keylength
* required.
*
- * The callback must return an OpenSSL::PKey::EC instance of the correct
- * key length.
+ * The callback is deprecated. This does not work with recent versions of
+ * OpenSSL. Use OpenSSL::SSL::SSLContext#ecdh_curves= instead.
*/
rb_attr(cSSLContext, rb_intern("tmp_ecdh_callback"), 1, 1, Qfalse);
+#endif
/*
* Sets the context in which a session can be reused. This allows
@@ -2132,7 +2305,7 @@ Init_ossl_ssl(void)
* end
*/
rb_attr(cSSLContext, rb_intern("renegotiation_cb"), 1, 1, Qfalse);
-#ifdef HAVE_OPENSSL_NPN_NEGOTIATED
+#ifdef HAVE_SSL_CTX_SET_NEXT_PROTO_SELECT_CB
/*
* An Enumerable of Strings. Each String represents a protocol to be
* advertised as the list of supported protocols for Next Protocol
@@ -2201,6 +2374,7 @@ Init_ossl_ssl(void)
rb_define_method(cSSLContext, "ssl_version=", ossl_sslctx_set_ssl_version, 1);
rb_define_method(cSSLContext, "ciphers", ossl_sslctx_get_ciphers, 0);
rb_define_method(cSSLContext, "ciphers=", ossl_sslctx_set_ciphers, 1);
+ rb_define_method(cSSLContext, "ecdh_curves=", ossl_sslctx_set_ecdh_curves, 1);
rb_define_method(cSSLContext, "setup", ossl_sslctx_setup, 0);
@@ -2280,9 +2454,11 @@ Init_ossl_ssl(void)
cSSLSocket = rb_define_class_under(mSSL, "SSLSocket", rb_cObject);
#ifdef OPENSSL_NO_SOCK
rb_define_const(mSSLExtConfig, "OPENSSL_NO_SOCK", Qtrue);
+ rb_define_method(cSSLSocket, "initialize", rb_f_notimplement, -1);
#else
rb_define_const(mSSLExtConfig, "OPENSSL_NO_SOCK", Qfalse);
rb_define_alloc_func(cSSLSocket, ossl_ssl_s_alloc);
+ rb_define_method(cSSLSocket, "initialize", ossl_ssl_initialize, -1);
rb_define_method(cSSLSocket, "connect", ossl_ssl_connect, 0);
rb_define_method(cSSLSocket, "connect_nonblock", ossl_ssl_connect_nonblock, -1);
rb_define_method(cSSLSocket, "accept", ossl_ssl_accept, 0);
@@ -2304,10 +2480,17 @@ Init_ossl_ssl(void)
rb_define_method(cSSLSocket, "session=", ossl_ssl_set_session, 1);
rb_define_method(cSSLSocket, "verify_result", ossl_ssl_get_verify_result, 0);
rb_define_method(cSSLSocket, "client_ca", ossl_ssl_get_client_ca_list, 0);
+#ifdef HAVE_SSL_SET_TLSEXT_HOST_NAME
+ /* #hostname is defined in lib/openssl/ssl.rb */
+ rb_define_method(cSSLSocket, "hostname=", ossl_ssl_set_hostname, 1);
+#endif
+# ifdef HAVE_SSL_GET_SERVER_TMP_KEY
+ rb_define_method(cSSLSocket, "tmp_key", ossl_ssl_tmp_key, 0);
+# endif
# ifdef HAVE_SSL_CTX_SET_ALPN_SELECT_CB
rb_define_method(cSSLSocket, "alpn_protocol", ossl_ssl_alpn_protocol, 0);
# endif
-# ifdef HAVE_OPENSSL_NPN_NEGOTIATED
+# ifdef HAVE_SSL_CTX_SET_NEXT_PROTO_SELECT_CB
rb_define_method(cSSLSocket, "npn_protocol", ossl_ssl_npn_protocol, 0);
# endif
#endif
@@ -2327,25 +2510,17 @@ Init_ossl_ssl(void)
ossl_ssl_def_const(OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG);
ossl_ssl_def_const(OP_SSLREF2_REUSE_CERT_TYPE_BUG);
ossl_ssl_def_const(OP_MICROSOFT_BIG_SSLV3_BUFFER);
-#if defined(SSL_OP_MSIE_SSLV2_RSA_PADDING)
ossl_ssl_def_const(OP_MSIE_SSLV2_RSA_PADDING);
-#endif
ossl_ssl_def_const(OP_SSLEAY_080_CLIENT_DH_BUG);
ossl_ssl_def_const(OP_TLS_D5_BUG);
ossl_ssl_def_const(OP_TLS_BLOCK_PADDING_BUG);
ossl_ssl_def_const(OP_DONT_INSERT_EMPTY_FRAGMENTS);
ossl_ssl_def_const(OP_ALL);
-#if defined(SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION)
ossl_ssl_def_const(OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION);
-#endif
-#if defined(SSL_OP_SINGLE_ECDH_USE)
ossl_ssl_def_const(OP_SINGLE_ECDH_USE);
-#endif
ossl_ssl_def_const(OP_SINGLE_DH_USE);
ossl_ssl_def_const(OP_EPHEMERAL_RSA);
-#if defined(SSL_OP_CIPHER_SERVER_PREFERENCE)
ossl_ssl_def_const(OP_CIPHER_SERVER_PREFERENCE);
-#endif
ossl_ssl_def_const(OP_TLS_ROLLBACK_BUG);
ossl_ssl_def_const(OP_NO_SSLv2);
ossl_ssl_def_const(OP_NO_SSLv3);
diff --git a/ext/openssl/ossl_ssl.h b/ext/openssl/ossl_ssl.h
index 909f6798..c1a3cd6c 100644
--- a/ext/openssl/ossl_ssl.h
+++ b/ext/openssl/ossl_ssl.h
@@ -12,6 +12,9 @@
#define GetSSL(obj, ssl) do { \
TypedData_Get_Struct((obj), SSL, &ossl_ssl_type, (ssl)); \
+ if (!(ssl)) { \
+ ossl_raise(rb_eRuntimeError, "SSL is not initialized"); \
+ } \
} while (0)
#define GetSSLSession(obj, sess) do { \
diff --git a/ext/openssl/ossl_ssl_session.c b/ext/openssl/ossl_ssl_session.c
index e1bbc6fb..1b6df55c 100644
--- a/ext/openssl/ossl_ssl_session.c
+++ b/ext/openssl/ossl_ssl_session.c
@@ -46,7 +46,7 @@ static VALUE ossl_ssl_session_initialize(VALUE self, VALUE arg1)
GetSSL(arg1, ssl);
- if (!ssl || (ctx = SSL_get1_session(ssl)) == NULL)
+ if ((ctx = SSL_get1_session(ssl)) == NULL)
ossl_raise(eSSLSession, "no session available");
} else {
BIO *in = ossl_obj2bio(arg1);
@@ -186,7 +186,6 @@ static VALUE ossl_ssl_session_set_timeout(VALUE self, VALUE time_v)
return ossl_ssl_session_get_timeout(self);
}
-#ifdef HAVE_SSL_SESSION_GET_ID
/*
* call-seq:
* session.id -> aString
@@ -205,7 +204,6 @@ static VALUE ossl_ssl_session_get_id(VALUE self)
return rb_str_new((const char *) p, i);
}
-#endif
/*
* call-seq:
@@ -316,12 +314,7 @@ void Init_ossl_ssl_session(void)
rb_define_method(cSSLSession, "time=", ossl_ssl_session_set_time, 1);
rb_define_method(cSSLSession, "timeout", ossl_ssl_session_get_timeout, 0);
rb_define_method(cSSLSession, "timeout=", ossl_ssl_session_set_timeout, 1);
-
-#ifdef HAVE_SSL_SESSION_GET_ID
rb_define_method(cSSLSession, "id", ossl_ssl_session_get_id, 0);
-#else
- rb_undef_method(cSSLSession, "id");
-#endif
rb_define_method(cSSLSession, "to_der", ossl_ssl_session_to_der, 0);
rb_define_method(cSSLSession, "to_pem", ossl_ssl_session_to_pem, 0);
rb_define_method(cSSLSession, "to_text", ossl_ssl_session_to_text, 0);
diff --git a/ext/openssl/ossl_x509.c b/ext/openssl/ossl_x509.c
index 2fd14566..cf62b53e 100644
--- a/ext/openssl/ossl_x509.c
+++ b/ext/openssl/ossl_x509.c
@@ -63,12 +63,8 @@ Init_ossl_x509(void)
DefX509Const(V_ERR_KEYUSAGE_NO_CERTSIGN);
DefX509Const(V_ERR_APPLICATION_VERIFICATION);
-#if defined(X509_V_FLAG_CRL_CHECK)
DefX509Const(V_FLAG_CRL_CHECK);
-#endif
-#if defined(X509_V_FLAG_CRL_CHECK_ALL)
DefX509Const(V_FLAG_CRL_CHECK_ALL);
-#endif
DefX509Const(PURPOSE_SSL_CLIENT);
DefX509Const(PURPOSE_SSL_SERVER);
@@ -77,21 +73,15 @@ Init_ossl_x509(void)
DefX509Const(PURPOSE_SMIME_ENCRYPT);
DefX509Const(PURPOSE_CRL_SIGN);
DefX509Const(PURPOSE_ANY);
-#if defined(X509_PURPOSE_OCSP_HELPER)
DefX509Const(PURPOSE_OCSP_HELPER);
-#endif
DefX509Const(TRUST_COMPAT);
DefX509Const(TRUST_SSL_CLIENT);
DefX509Const(TRUST_SSL_SERVER);
DefX509Const(TRUST_EMAIL);
DefX509Const(TRUST_OBJECT_SIGN);
-#if defined(X509_TRUST_OCSP_SIGN)
DefX509Const(TRUST_OCSP_SIGN);
-#endif
-#if defined(X509_TRUST_OCSP_REQUEST)
DefX509Const(TRUST_OCSP_REQUEST);
-#endif
DefX509Default(CERT_AREA, cert_area);
DefX509Default(CERT_DIR, cert_dir);
diff --git a/ext/openssl/ossl_x509attr.c b/ext/openssl/ossl_x509attr.c
index d0f41c6b..7cd3fe6d 100644
--- a/ext/openssl/ossl_x509attr.c
+++ b/ext/openssl/ossl_x509attr.c
@@ -141,7 +141,7 @@ ossl_x509attr_set_oid(VALUE self, VALUE oid)
ASN1_OBJECT *obj;
char *s;
- s = StringValuePtr(oid);
+ s = StringValueCStr(oid);
obj = OBJ_txt2obj(s, 0);
if(!obj) obj = OBJ_txt2obj(s, 1);
if(!obj) ossl_raise(eX509AttrError, NULL);
@@ -178,14 +178,6 @@ ossl_x509attr_get_oid(VALUE self)
return ret;
}
-#if defined(HAVE_ST_X509_ATTRIBUTE_SINGLE) || defined(HAVE_ST_SINGLE)
-# define OSSL_X509ATTR_IS_SINGLE(attr) ((attr)->single)
-# define OSSL_X509ATTR_SET_SINGLE(attr) ((attr)->single = 1)
-#else
-# define OSSL_X509ATTR_IS_SINGLE(attr) (!(attr)->value.set)
-# define OSSL_X509ATTR_SET_SINGLE(attr) ((attr)->value.set = 0)
-#endif
-
/*
* call-seq:
* attr.value = asn1 => asn1
@@ -196,6 +188,7 @@ ossl_x509attr_set_value(VALUE self, VALUE value)
X509_ATTRIBUTE *attr;
ASN1_TYPE *a1type;
+ OSSL_Check_Kind(value, cASN1Data);
if(!(a1type = ossl_asn1_get_asn1type(value)))
ossl_raise(eASN1Error, "could not get ASN1_TYPE");
if(ASN1_TYPE_get(a1type) == V_ASN1_SEQUENCE){
@@ -204,10 +197,10 @@ ossl_x509attr_set_value(VALUE self, VALUE value)
}
GetX509Attr(self, attr);
if(attr->value.set){
- if(OSSL_X509ATTR_IS_SINGLE(attr)) ASN1_TYPE_free(attr->value.single);
+ if(attr->single) ASN1_TYPE_free(attr->value.single);
else sk_ASN1_TYPE_free(attr->value.set);
}
- OSSL_X509ATTR_SET_SINGLE(attr);
+ attr->single = 1;
attr->value.single = a1type;
return value;
@@ -227,7 +220,7 @@ ossl_x509attr_get_value(VALUE self)
GetX509Attr(self, attr);
if(attr->value.ptr == NULL) return Qnil;
- if(OSSL_X509ATTR_IS_SINGLE(attr)){
+ if(attr->single){
length = i2d_ASN1_TYPE(attr->value.single, NULL);
str = rb_str_new(0, length);
p = (unsigned char *)RSTRING_PTR(str);
@@ -268,7 +261,7 @@ ossl_x509attr_to_der(VALUE self)
p = (unsigned char *)RSTRING_PTR(str);
if(i2d_X509_ATTRIBUTE(attr, &p) <= 0)
ossl_raise(eX509AttrError, NULL);
- rb_str_set_len(str, p - (unsigned char*)RSTRING_PTR(str));
+ ossl_str_adjust(str, p);
return str;
}
diff --git a/ext/openssl/ossl_x509cert.c b/ext/openssl/ossl_x509cert.c
index 4dafae17..34b8aae7 100644
--- a/ext/openssl/ossl_x509cert.c
+++ b/ext/openssl/ossl_x509cert.c
@@ -78,9 +78,9 @@ ossl_x509_new_from_file(VALUE filename)
FILE *fp;
VALUE obj;
- SafeStringValue(filename);
+ rb_check_safe_obj(filename);
obj = NewX509(cX509Cert);
- if (!(fp = fopen(RSTRING_PTR(filename), "r"))) {
+ if (!(fp = fopen(StringValueCStr(filename), "r"))) {
ossl_raise(eX509CertError, "%s", strerror(errno));
}
rb_fd_fix_cloexec(fileno(fp));
@@ -591,18 +591,19 @@ ossl_x509_verify(VALUE self, VALUE key)
{
X509 *x509;
EVP_PKEY *pkey;
- int i;
pkey = GetPKeyPtr(key); /* NO NEED TO DUP */
GetX509(self, x509);
- if ((i = X509_verify(x509, pkey)) < 0) {
- ossl_raise(eX509CertError, NULL);
- }
- if (i > 0) {
+
+ switch (X509_verify(x509, pkey)) {
+ case 1:
return Qtrue;
+ case 0:
+ ossl_clear_error();
+ return Qfalse;
+ default:
+ ossl_raise(eX509CertError, NULL);
}
-
- return Qfalse;
}
/*
diff --git a/ext/openssl/ossl_x509crl.c b/ext/openssl/ossl_x509crl.c
index f64712ef..a660ccce 100644
--- a/ext/openssl/ossl_x509crl.c
+++ b/ext/openssl/ossl_x509crl.c
@@ -360,17 +360,17 @@ static VALUE
ossl_x509crl_verify(VALUE self, VALUE key)
{
X509_CRL *crl;
- int ret;
GetX509CRL(self, crl);
- if ((ret = X509_CRL_verify(crl, GetPKeyPtr(key))) < 0) {
- ossl_raise(eX509CRLError, NULL);
- }
- if (ret == 1) {
+ switch (X509_CRL_verify(crl, GetPKeyPtr(key))) {
+ case 1:
return Qtrue;
+ case 0:
+ ossl_clear_error();
+ return Qfalse;
+ default:
+ ossl_raise(eX509CRLError, NULL);
}
-
- return Qfalse;
}
static VALUE
diff --git a/ext/openssl/ossl_x509ext.c b/ext/openssl/ossl_x509ext.c
index 70a117cc..e5817543 100644
--- a/ext/openssl/ossl_x509ext.c
+++ b/ext/openssl/ossl_x509ext.c
@@ -188,7 +188,6 @@ ossl_x509extfactory_set_crl(VALUE self, VALUE crl)
return crl;
}
-#ifdef HAVE_X509V3_SET_NCONF
static VALUE
ossl_x509extfactory_set_config(VALUE self, VALUE config)
{
@@ -202,9 +201,6 @@ ossl_x509extfactory_set_config(VALUE self, VALUE config)
return config;
}
-#else
-#define ossl_x509extfactory_set_config rb_f_notimplement
-#endif
static VALUE
ossl_x509extfactory_initialize(int argc, VALUE *argv, VALUE self)
@@ -243,36 +239,29 @@ ossl_x509extfactory_create_ext(int argc, VALUE *argv, VALUE self)
X509_EXTENSION *ext;
VALUE oid, value, critical, valstr, obj;
int nid;
-#ifdef HAVE_X509V3_EXT_NCONF_NID
VALUE rconf;
CONF *conf;
-#else
- static LHASH *empty_lhash;
-#endif
rb_scan_args(argc, argv, "21", &oid, &value, &critical);
- StringValue(oid);
+ StringValueCStr(oid);
StringValue(value);
if(NIL_P(critical)) critical = Qfalse;
nid = OBJ_ln2nid(RSTRING_PTR(oid));
if(!nid) nid = OBJ_sn2nid(RSTRING_PTR(oid));
- if(!nid) ossl_raise(eX509ExtError, "unknown OID `%s'", RSTRING_PTR(oid));
+ if(!nid) ossl_raise(eX509ExtError, "unknown OID `%"PRIsVALUE"'", oid);
+
valstr = rb_str_new2(RTEST(critical) ? "critical," : "");
rb_str_append(valstr, value);
+ StringValueCStr(valstr);
+
GetX509ExtFactory(self, ctx);
obj = NewX509Ext(cX509Ext);
-#ifdef HAVE_X509V3_EXT_NCONF_NID
rconf = rb_iv_get(self, "@config");
conf = NIL_P(rconf) ? NULL : GetConfigPtr(rconf);
ext = X509V3_EXT_nconf_nid(conf, ctx, nid, RSTRING_PTR(valstr));
-#else
- if (!empty_lhash) empty_lhash = lh_new(NULL, NULL);
- ext = X509V3_EXT_conf_nid(empty_lhash, ctx, nid, RSTRING_PTR(valstr));
-#endif
if (!ext){
- ossl_raise(eX509ExtError, "%s = %s",
- RSTRING_PTR(oid), RSTRING_PTR(value));
+ ossl_raise(eX509ExtError, "%"PRIsVALUE" = %"PRIsVALUE, oid, valstr);
}
SetX509Ext(obj, ext);
@@ -341,7 +330,7 @@ ossl_x509ext_set_oid(VALUE self, VALUE oid)
ASN1_OBJECT *obj;
char *s;
- s = StringValuePtr(oid);
+ s = StringValueCStr(oid);
obj = OBJ_txt2obj(s, 0);
if(!obj) obj = OBJ_txt2obj(s, 1);
if(!obj) ossl_raise(eX509ExtError, NULL);
@@ -356,23 +345,16 @@ ossl_x509ext_set_value(VALUE self, VALUE data)
{
X509_EXTENSION *ext;
ASN1_OCTET_STRING *asn1s;
- char *s;
data = ossl_to_der_if_possible(data);
StringValue(data);
- if(!(s = OPENSSL_malloc(RSTRING_LEN(data))))
- ossl_raise(eX509ExtError, "malloc error");
- memcpy(s, RSTRING_PTR(data), RSTRING_LEN(data));
if(!(asn1s = ASN1_OCTET_STRING_new())){
- OPENSSL_free(s);
ossl_raise(eX509ExtError, NULL);
}
- if(!M_ASN1_OCTET_STRING_set(asn1s, s, RSTRING_LENINT(data))){
- OPENSSL_free(s);
+ if(!ASN1_STRING_set((ASN1_STRING *)asn1s, (unsigned char *)RSTRING_PTR(data), RSTRING_LENINT(data))){
ASN1_OCTET_STRING_free(asn1s);
ossl_raise(eX509ExtError, NULL);
}
- OPENSSL_free(s);
GetX509Ext(self, ext);
X509_EXTENSION_set_data(ext, asn1s);
@@ -424,7 +406,7 @@ ossl_x509ext_get_value(VALUE obj)
if (!(out = BIO_new(BIO_s_mem())))
ossl_raise(eX509ExtError, NULL);
if (!X509V3_EXT_print(out, ext, 0, 0))
- M_ASN1_OCTET_STRING_print(out, ext->value);
+ ASN1_STRING_print(out, (ASN1_STRING *)X509_EXTENSION_get_data(ext));
ret = ossl_membio2str(out);
return ret;
diff --git a/ext/openssl/ossl_x509req.c b/ext/openssl/ossl_x509req.c
index e5ce088a..c1cdca5f 100644
--- a/ext/openssl/ossl_x509req.c
+++ b/ext/openssl/ossl_x509req.c
@@ -375,18 +375,18 @@ ossl_x509req_verify(VALUE self, VALUE key)
{
X509_REQ *req;
EVP_PKEY *pkey;
- int i;
GetX509Req(self, req);
pkey = GetPKeyPtr(key); /* NO NEED TO DUP */
- if ((i = X509_REQ_verify(req, pkey)) < 0) {
- ossl_raise(eX509ReqError, NULL);
- }
- if (i > 0) {
+ switch (X509_REQ_verify(req, pkey)) {
+ case 1:
return Qtrue;
+ case 0:
+ ossl_clear_error();
+ return Qfalse;
+ default:
+ ossl_raise(eX509ReqError, NULL);
}
-
- return Qfalse;
}
static VALUE
diff --git a/ext/openssl/ossl_x509store.c b/ext/openssl/ossl_x509store.c
index bb6fe14d..767e30be 100644
--- a/ext/openssl/ossl_x509store.c
+++ b/ext/openssl/ossl_x509store.c
@@ -130,7 +130,7 @@ ossl_x509store_set_vfy_cb(VALUE self, VALUE cb)
X509_STORE *store;
GetX509Store(self, store);
- X509_STORE_set_ex_data(store, ossl_verify_cb_idx, (void*)cb);
+ X509_STORE_set_ex_data(store, ossl_store_ex_verify_cb_idx, (void *)cb);
rb_iv_set(self, "@verify_callback", cb);
return cb;
@@ -153,12 +153,6 @@ ossl_x509store_initialize(int argc, VALUE *argv, VALUE self)
X509_STORE_set_verify_cb_func(store, ossl_verify_cb);
ossl_x509store_set_vfy_cb(self, Qnil);
-#if (OPENSSL_VERSION_NUMBER < 0x00907000L)
- rb_iv_set(self, "@flags", INT2FIX(0));
- rb_iv_set(self, "@purpose", INT2FIX(0));
- rb_iv_set(self, "@trust", INT2FIX(0));
-#endif
-
/* last verification status */
rb_iv_set(self, "@error", Qnil);
rb_iv_set(self, "@error_string", Qnil);
@@ -171,15 +165,11 @@ ossl_x509store_initialize(int argc, VALUE *argv, VALUE self)
static VALUE
ossl_x509store_set_flags(VALUE self, VALUE flags)
{
-#if (OPENSSL_VERSION_NUMBER >= 0x00907000L)
X509_STORE *store;
long f = NUM2LONG(flags);
GetX509Store(self, store);
X509_STORE_set_flags(store, f);
-#else
- rb_iv_set(self, "@flags", flags);
-#endif
return flags;
}
@@ -187,15 +177,11 @@ ossl_x509store_set_flags(VALUE self, VALUE flags)
static VALUE
ossl_x509store_set_purpose(VALUE self, VALUE purpose)
{
-#if (OPENSSL_VERSION_NUMBER >= 0x00907000L)
X509_STORE *store;
int p = NUM2INT(purpose);
GetX509Store(self, store);
X509_STORE_set_purpose(store, p);
-#else
- rb_iv_set(self, "@purpose", purpose);
-#endif
return purpose;
}
@@ -203,15 +189,11 @@ ossl_x509store_set_purpose(VALUE self, VALUE purpose)
static VALUE
ossl_x509store_set_trust(VALUE self, VALUE trust)
{
-#if (OPENSSL_VERSION_NUMBER >= 0x00907000L)
X509_STORE *store;
int t = NUM2INT(trust);
GetX509Store(self, store);
X509_STORE_set_trust(store, t);
-#else
- rb_iv_set(self, "@trust", trust);
-#endif
return trust;
}
@@ -240,8 +222,8 @@ ossl_x509store_add_file(VALUE self, VALUE file)
char *path = NULL;
if(file != Qnil){
- SafeStringValue(file);
- path = RSTRING_PTR(file);
+ rb_check_safe_obj(file);
+ path = StringValueCStr(file);
}
GetX509Store(self, store);
lookup = X509_STORE_add_lookup(store, X509_LOOKUP_file());
@@ -261,8 +243,8 @@ ossl_x509store_add_path(VALUE self, VALUE dir)
char *path = NULL;
if(dir != Qnil){
- SafeStringValue(dir);
- path = RSTRING_PTR(dir);
+ rb_check_safe_obj(dir);
+ path = StringValueCStr(dir);
}
GetX509Store(self, store);
lookup = X509_STORE_add_lookup(store, X509_LOOKUP_hash_dir());
@@ -441,17 +423,10 @@ ossl_x509stctx_initialize(int argc, VALUE *argv, VALUE self)
SafeGetX509Store(store, x509st);
if(!NIL_P(cert)) x509 = DupX509CertPtr(cert); /* NEED TO DUP */
if(!NIL_P(chain)) x509s = ossl_x509_ary2sk(chain);
-#if (OPENSSL_VERSION_NUMBER >= 0x00907000L)
if(X509_STORE_CTX_init(ctx, x509st, x509, x509s) != 1){
sk_X509_pop_free(x509s, X509_free);
ossl_raise(eX509StoreError, NULL);
}
-#else
- X509_STORE_CTX_init(ctx, x509st, x509, x509s);
- ossl_x509stctx_set_flags(self, rb_iv_get(store, "@flags"));
- ossl_x509stctx_set_purpose(self, rb_iv_get(store, "@purpose"));
- ossl_x509stctx_set_trust(self, rb_iv_get(store, "@trust"));
-#endif
if (!NIL_P(t = rb_iv_get(store, "@time")))
ossl_x509stctx_set_time(self, t);
rb_iv_set(self, "@verify_callback", rb_iv_get(store, "@verify_callback"));
@@ -464,14 +439,20 @@ static VALUE
ossl_x509stctx_verify(VALUE self)
{
X509_STORE_CTX *ctx;
- int result;
GetX509StCtx(self, ctx);
- X509_STORE_CTX_set_ex_data(ctx, ossl_verify_cb_idx,
- (void*)rb_iv_get(self, "@verify_callback"));
- result = X509_verify_cert(ctx);
-
- return result ? Qtrue : Qfalse;
+ X509_STORE_CTX_set_ex_data(ctx, ossl_store_ctx_ex_verify_cb_idx,
+ (void *)rb_iv_get(self, "@verify_callback"));
+
+ switch (X509_verify_cert(ctx)) {
+ case 1:
+ return Qtrue;
+ case 0:
+ ossl_clear_error();
+ return Qfalse;
+ default:
+ ossl_raise(eX509CertError, NULL);
+ }
}
static VALUE
@@ -556,16 +537,12 @@ ossl_x509stctx_get_curr_cert(VALUE self)
static VALUE
ossl_x509stctx_get_curr_crl(VALUE self)
{
-#if (OPENSSL_VERSION_NUMBER >= 0x00907000L)
X509_STORE_CTX *ctx;
GetX509StCtx(self, ctx);
if(!ctx->current_crl) return Qnil;
return ossl_x509crl_new(ctx->current_crl);
-#else
- return Qnil;
-#endif
}
static VALUE
diff --git a/lib/openssl/buffering.rb b/lib/openssl/buffering.rb
index d0821990..61e1f43e 100644
--- a/lib/openssl/buffering.rb
+++ b/lib/openssl/buffering.rb
@@ -132,7 +132,6 @@ module OpenSSL::Buffering
buf.replace(ret)
ret = buf
end
- raise EOFError if ret.empty?
ret
end
@@ -182,7 +181,6 @@ module OpenSSL::Buffering
buf.replace(ret)
ret = buf
end
- raise EOFError if ret.empty?
ret
end
diff --git a/lib/openssl/ssl.rb b/lib/openssl/ssl.rb
index 57519f2c..00c32753 100644
--- a/lib/openssl/ssl.rb
+++ b/lib/openssl/ssl.rb
@@ -56,19 +56,16 @@ module OpenSSL
}.join(":"),
:options => -> {
opts = OpenSSL::SSL::OP_ALL
- opts &= ~OpenSSL::SSL::OP_DONT_INSERT_EMPTY_FRAGMENTS if defined?(OpenSSL::SSL::OP_DONT_INSERT_EMPTY_FRAGMENTS)
+ opts &= ~OpenSSL::SSL::OP_DONT_INSERT_EMPTY_FRAGMENTS
opts |= OpenSSL::SSL::OP_NO_COMPRESSION if defined?(OpenSSL::SSL::OP_NO_COMPRESSION)
- opts |= OpenSSL::SSL::OP_NO_SSLv2 if defined?(OpenSSL::SSL::OP_NO_SSLv2)
- opts |= OpenSSL::SSL::OP_NO_SSLv3 if defined?(OpenSSL::SSL::OP_NO_SSLv3)
+ opts |= OpenSSL::SSL::OP_NO_SSLv2 | OpenSSL::SSL::OP_NO_SSLv3
opts
}.call
}
DEFAULT_CERT_STORE = OpenSSL::X509::Store.new
DEFAULT_CERT_STORE.set_default_paths
- if defined?(OpenSSL::X509::V_FLAG_CRL_CHECK_ALL)
- DEFAULT_CERT_STORE.flags = OpenSSL::X509::V_FLAG_CRL_CHECK_ALL
- end
+ DEFAULT_CERT_STORE.flags = OpenSSL::X509::V_FLAG_CRL_CHECK_ALL
INIT_VARS = ["cert", "key", "client_ca", "ca_file", "ca_path",
"timeout", "verify_mode", "verify_depth", "renegotiation_cb",
@@ -250,47 +247,21 @@ module OpenSSL
include Buffering
include SocketForwarder
- if ExtConfig::OPENSSL_NO_SOCK
- def initialize(io, ctx = nil); raise NotImplementedError; end
- else
- if ExtConfig::HAVE_TLSEXT_HOST_NAME
- attr_accessor :hostname
- end
-
- attr_reader :io, :context
- attr_accessor :sync_close
- alias :to_io :io
-
- # call-seq:
- # SSLSocket.new(io) => aSSLSocket
- # SSLSocket.new(io, ctx) => aSSLSocket
- #
- # Creates a new SSL socket from +io+ which must be a real ruby object (not an
- # IO-like object that responds to read/write).
- #
- # If +ctx+ is provided the SSL Sockets initial params will be taken from
- # the context.
- #
- # The OpenSSL::Buffering module provides additional IO methods.
- #
- # This method will freeze the SSLContext if one is provided;
- # however, session management is still allowed in the frozen SSLContext.
-
- def initialize(io, context = OpenSSL::SSL::SSLContext.new)
- @io = io
- @context = context
- @sync_close = false
- @hostname = nil
- @io.nonblock = true if @io.respond_to?(:nonblock=)
- context.setup
- super()
- end
+ if ExtConfig::HAVE_TLSEXT_HOST_NAME
+ attr_reader :hostname
end
+ attr_reader :io, :context
+ attr_accessor :sync_close
+ alias :to_io :io
+
# call-seq:
# ssl.sysclose => nil
#
- # Shuts down the SSL connection and prepares it for another connection.
+ # Sends "close notify" to the peer and tries to shut down the SSL
+ # connection gracefully.
+ #
+ # If sync_close is set to +true+, the underlying IO is also closed.
def sysclose
return if closed?
stop
diff --git a/test/test_asn1.rb b/test/test_asn1.rb
index fd2118d8..9db9ec51 100644
--- a/test/test_asn1.rb
+++ b/test/test_asn1.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: false
require_relative 'utils'
-class OpenSSL::TestASN1 < Test::Unit::TestCase
+class OpenSSL::TestASN1 < OpenSSL::TestCase
def test_decode
subj = OpenSSL::X509::Name.parse("/DC=org/DC=ruby-lang/CN=TestCA")
key = OpenSSL::TestUtils::TEST_KEY_RSA1024
diff --git a/test/test_bn.rb b/test/test_bn.rb
index 848d1feb..37ba5e55 100644
--- a/test/test_bn.rb
+++ b/test/test_bn.rb
@@ -3,7 +3,7 @@ require_relative 'utils'
if defined?(OpenSSL::TestUtils)
-class OpenSSL::TestBN < Test::Unit::TestCase
+class OpenSSL::TestBN < OpenSSL::TestCase
def test_new_str
e1 = OpenSSL::BN.new(999.to_s(16), 16) # OpenSSL::BN.new(str, 16) must be most stable
e2 = OpenSSL::BN.new((2**107-1).to_s(16), 16)
@@ -43,10 +43,18 @@ class OpenSSL::TestBN < Test::Unit::TestCase
assert_equal(true, OpenSSL::BN.new((2 ** 127 - 1).to_s(16), 16).prime?(1))
end
- def test_cmp_nil
- bn = OpenSSL::BN.new('1')
- assert_equal(false, bn == nil)
- assert_equal(true, bn != nil)
+ def test_cmp
+ bn1 = OpenSSL::BN.new('1')
+ bn2 = OpenSSL::BN.new('1')
+ bn3 = OpenSSL::BN.new('2')
+ assert_equal(false, bn1 == nil)
+ assert_equal(true, bn1 != nil)
+ assert_equal(true, bn1 == bn2)
+ assert_equal(false, bn1 == bn3)
+ assert_equal(true, bn1.eql?(bn2))
+ assert_equal(false, bn1.eql?(bn3))
+ assert_equal(bn1.hash, bn2.hash)
+ assert_not_equal(bn3.hash, bn1.hash)
end
end
diff --git a/test/test_buffering.rb b/test/test_buffering.rb
index fe07b46a..1f42cd3c 100644
--- a/test/test_buffering.rb
+++ b/test/test_buffering.rb
@@ -2,7 +2,7 @@
require_relative 'utils'
require 'stringio'
-class OpenSSL::TestBuffering < Test::Unit::TestCase
+class OpenSSL::TestBuffering < OpenSSL::TestCase
class IO
include OpenSSL::Buffering
@@ -43,19 +43,19 @@ class OpenSSL::TestBuffering < Test::Unit::TestCase
def test_flush
@io.write 'a'
- refute @io.sync
+ assert_not_predicate @io, :sync
assert_empty @io.string
assert_equal @io, @io.flush
- refute @io.sync
+ assert_not_predicate @io, :sync
assert_equal 'a', @io.string
end
def test_flush_error
@io.write 'a'
- refute @io.sync
+ assert_not_predicate @io, :sync
assert_empty @io.string
def @io.syswrite *a
@@ -66,7 +66,7 @@ class OpenSSL::TestBuffering < Test::Unit::TestCase
@io.flush
end
- refute @io.sync, 'sync must not change'
+ assert_not_predicate @io, :sync, 'sync must not change'
end
def test_getc
diff --git a/test/test_cipher.rb b/test/test_cipher.rb
index 89c176f4..ec14f467 100644
--- a/test/test_cipher.rb
+++ b/test/test_cipher.rb
@@ -3,7 +3,7 @@ require_relative 'utils'
if defined?(OpenSSL::TestUtils)
-class OpenSSL::TestCipher < Test::Unit::TestCase
+class OpenSSL::TestCipher < OpenSSL::TestCase
class << self
@@ -34,6 +34,7 @@ class OpenSSL::TestCipher < Test::Unit::TestCase
end
def teardown
+ super
@c1 = @c2 = nil
end
@@ -53,8 +54,8 @@ class OpenSSL::TestCipher < Test::Unit::TestCase
def test_info
assert_equal("DES-EDE3-CBC", @c1.name, "name")
assert_equal("DES-EDE3-CBC", @c2.name, "name")
- assert_kind_of(Fixnum, @c1.key_len, "key_len")
- assert_kind_of(Fixnum, @c1.iv_len, "iv_len")
+ assert_kind_of(Integer, @c1.key_len, "key_len")
+ assert_kind_of(Integer, @c1.iv_len, "iv_len")
end
def test_dup
@@ -79,6 +80,18 @@ class OpenSSL::TestCipher < Test::Unit::TestCase
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 }
+ end
+
def test_empty_data
@c1.encrypt
assert_raise(ArgumentError){ @c1.update("") }
@@ -101,40 +114,38 @@ class OpenSSL::TestCipher < Test::Unit::TestCase
end
end if has_cipher?('aes-128-ctr')
- if OpenSSL::OPENSSL_VERSION_NUMBER > 0x00907000
- def test_ciphers
- OpenSSL::Cipher.ciphers.each{|name|
- next if /netbsd/ =~ RUBY_PLATFORM && /idea|rc5/i =~ name
- begin
- assert_kind_of(OpenSSL::Cipher::Cipher, OpenSSL::Cipher::Cipher.new(name))
- rescue OpenSSL::Cipher::CipherError => e
- next if /wrap/ =~ name and e.message == 'wrap mode not allowed'
- raise
- end
- }
- end
+ def test_ciphers
+ OpenSSL::Cipher.ciphers.each{|name|
+ next if /netbsd/ =~ RUBY_PLATFORM && /idea|rc5/i =~ name
+ begin
+ assert_kind_of(OpenSSL::Cipher::Cipher, OpenSSL::Cipher::Cipher.new(name))
+ rescue OpenSSL::Cipher::CipherError => e
+ next if /wrap/ =~ name and e.message == 'wrap mode not allowed'
+ raise
+ end
+ }
+ end
- def test_AES
- pt = File.read(__FILE__)
- %w(ECB CBC CFB OFB).each{|mode|
- c1 = OpenSSL::Cipher::AES256.new(mode)
- c1.encrypt
- c1.pkcs5_keyivgen("passwd")
- ct = c1.update(pt) + c1.final
-
- c2 = OpenSSL::Cipher::AES256.new(mode)
- c2.decrypt
- c2.pkcs5_keyivgen("passwd")
- assert_equal(pt, c2.update(ct) + c2.final)
- }
- end
+ def test_AES
+ pt = File.read(__FILE__)
+ %w(ECB CBC CFB OFB).each{|mode|
+ c1 = OpenSSL::Cipher::AES256.new(mode)
+ c1.encrypt
+ c1.pkcs5_keyivgen("passwd")
+ ct = c1.update(pt) + c1.final
+
+ c2 = OpenSSL::Cipher::AES256.new(mode)
+ c2.decrypt
+ c2.pkcs5_keyivgen("passwd")
+ assert_equal(pt, c2.update(ct) + c2.final)
+ }
+ 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_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
end
end
@@ -143,9 +154,9 @@ class OpenSSL::TestCipher < Test::Unit::TestCase
def test_authenticated
cipher = OpenSSL::Cipher.new('aes-128-gcm')
- assert(cipher.authenticated?)
+ assert_predicate(cipher, :authenticated?)
cipher = OpenSSL::Cipher.new('aes-128-cbc')
- refute(cipher.authenticated?)
+ assert_not_predicate(cipher, :authenticated?)
end
def test_aes_gcm
diff --git a/test/test_config.rb b/test/test_config.rb
index 812b28b9..3e2e1273 100644
--- a/test/test_config.rb
+++ b/test/test_config.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: false
require_relative 'utils'
-class OpenSSL::TestConfig < Test::Unit::TestCase
+class OpenSSL::TestConfig < OpenSSL::TestCase
def setup
file = Tempfile.open("openssl.cnf")
file << <<__EOD__
@@ -18,6 +18,7 @@ __EOD__
end
def teardown
+ super
@tmpfile.close!
end
diff --git a/test/test_digest.rb b/test/test_digest.rb
index 8b724a03..ba3e974b 100644
--- a/test/test_digest.rb
+++ b/test/test_digest.rb
@@ -3,7 +3,7 @@ require_relative 'utils'
if defined?(OpenSSL::TestUtils)
-class OpenSSL::TestDigest < Test::Unit::TestCase
+class OpenSSL::TestDigest < OpenSSL::TestCase
def setup
@d1 = OpenSSL::Digest.new("MD5")
@d2 = OpenSSL::Digest::MD5.new
@@ -12,6 +12,7 @@ class OpenSSL::TestDigest < Test::Unit::TestCase
end
def teardown
+ super
@d1 = @d2 = @md = nil
end
diff --git a/test/test_engine.rb b/test/test_engine.rb
index 3521de63..9a0da340 100644
--- a/test/test_engine.rb
+++ b/test/test_engine.rb
@@ -1,9 +1,10 @@
# frozen_string_literal: false
require_relative 'utils'
-class OpenSSL::TestEngine < Test::Unit::TestCase
+class OpenSSL::TestEngine < OpenSSL::TestCase
def teardown
+ super
OpenSSL::Engine.cleanup # [ruby-core:40669]
assert_equal(0, OpenSSL::Engine.engines.size)
end
diff --git a/test/test_fips.rb b/test/test_fips.rb
index 33769c93..534dade0 100644
--- a/test/test_fips.rb
+++ b/test/test_fips.rb
@@ -3,7 +3,7 @@ require_relative 'utils'
if defined?(OpenSSL::TestUtils)
-class OpenSSL::TestFIPS < Test::Unit::TestCase
+class OpenSSL::TestFIPS < OpenSSL::TestCase
def test_fips_mode_is_reentrant
OpenSSL.fips_mode = false
diff --git a/test/test_hmac.rb b/test/test_hmac.rb
index 135d26f0..3c90a5de 100644
--- a/test/test_hmac.rb
+++ b/test/test_hmac.rb
@@ -3,7 +3,7 @@
require_relative 'utils'
-class OpenSSL::TestHMAC < Test::Unit::TestCase
+class OpenSSL::TestHMAC < OpenSSL::TestCase
def setup
@digest = OpenSSL::Digest::MD5
@key = "KEY"
@@ -12,9 +12,6 @@ class OpenSSL::TestHMAC < Test::Unit::TestCase
@h2 = OpenSSL::HMAC.new(@key, "MD5")
end
- def teardown
- end
-
def test_hmac
@h1.update(@data)
@h2.update(@data)
diff --git a/test/test_ns_spki.rb b/test/test_ns_spki.rb
index 4f6e6f59..4740c0b2 100644
--- a/test/test_ns_spki.rb
+++ b/test/test_ns_spki.rb
@@ -3,7 +3,7 @@ require_relative 'utils'
if defined?(OpenSSL::TestUtils)
-class OpenSSL::TestNSSPI < Test::Unit::TestCase
+class OpenSSL::TestNSSPI < OpenSSL::TestCase
def setup
# This request data is adopt from the specification of
# "Netscape Extensions for User Key Generation".
diff --git a/test/test_ocsp.rb b/test/test_ocsp.rb
index 1a969fd7..d04b4216 100644
--- a/test/test_ocsp.rb
+++ b/test/test_ocsp.rb
@@ -3,7 +3,7 @@ require_relative "utils"
if defined?(OpenSSL::TestUtils)
-class OpenSSL::TestOCSP < Test::Unit::TestCase
+class OpenSSL::TestOCSP < OpenSSL::TestCase
def setup
ca_subj = OpenSSL::X509::Name.parse("/DC=org/DC=ruby-lang/CN=TestCA")
ca_key = OpenSSL::TestUtils::TEST_KEY_RSA1024
diff --git a/test/test_pair.rb b/test/test_pair.rb
index c7fc292e..c8770690 100644
--- a/test/test_pair.rb
+++ b/test/test_pair.rb
@@ -280,6 +280,35 @@ module OpenSSL::TestPairM
}
end
+ def test_write_nonblock_retry
+ ssl_pair {|s1, s2|
+ # fill up a socket so we hit EAGAIN
+ written = String.new
+ n = 0
+ buf = 'a' * 11
+ case ret = s1.write_nonblock(buf, exception: false)
+ when :wait_readable then break
+ when :wait_writable then break
+ when Integer
+ written << buf
+ n += ret
+ exp = buf.bytesize
+ if ret != exp
+ buf = buf.byteslice(ret, exp - ret)
+ end
+ end while true
+ assert_kind_of Symbol, ret
+
+ # make more space for subsequent write:
+ readed = s2.read(n)
+ assert_equal written, readed
+
+ # this fails if SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER is missing:
+ buf2 = Marshal.load(Marshal.dump(buf))
+ assert_kind_of Integer, s1.write_nonblock(buf2, exception: false)
+ }
+ end
+
def tcp_pair
host = "127.0.0.1"
serv = TCPServer.new(host, 0)
@@ -343,41 +372,73 @@ module OpenSSL::TestPairM
end
def test_ecdh_callback
- called = false
- ctx2 = OpenSSL::SSL::SSLContext.new
- ctx2.ciphers = "ECDH"
- ctx2.tmp_ecdh_callback = ->(*args) {
- called = true
- OpenSSL::PKey::EC.new "prime256v1"
- }
+ return unless OpenSSL::SSL::SSLContext.instance_methods.include?(:tmp_ecdh_callback)
+ EnvUtil.suppress_warning do # tmp_ecdh_callback is deprecated (2016-05)
+ begin
+ called = false
+ ctx2 = OpenSSL::SSL::SSLContext.new
+ ctx2.ciphers = "ECDH"
+ ctx2.tmp_ecdh_callback = ->(*args) {
+ called = true
+ OpenSSL::PKey::EC.new "prime256v1"
+ }
+
+ sock1, sock2 = tcp_pair
+
+ s2 = OpenSSL::SSL::SSLSocket.new(sock2, ctx2)
+ ctx1 = OpenSSL::SSL::SSLContext.new
+ ctx1.ciphers = "ECDH"
+
+ s1 = OpenSSL::SSL::SSLSocket.new(sock1, ctx1)
+ th = Thread.new do
+ begin
+ rv = s1.connect_nonblock(exception: false)
+ case rv
+ when :wait_writable
+ IO.select(nil, [s1], nil, 5)
+ when :wait_readable
+ IO.select([s1], nil, nil, 5)
+ end
+ end until rv == s1
+ end
+
+ accepted = s2.accept
+ assert called, 'ecdh callback should be called'
+ rescue OpenSSL::SSL::SSLError => e
+ if e.message =~ /no cipher match/
+ skip "ECDH cipher not supported."
+ else
+ raise e
+ end
+ ensure
+ th.join if th
+ s1.close if s1
+ s2.close if s2
+ sock1.close if sock1
+ sock2.close if sock2
+ end
+ end
+ end
+ def test_ecdh_curves
sock1, sock2 = tcp_pair
- s2 = OpenSSL::SSL::SSLSocket.new(sock2, ctx2)
ctx1 = OpenSSL::SSL::SSLContext.new
ctx1.ciphers = "ECDH"
-
+ ctx1.ecdh_curves = "P-384:P-521"
s1 = OpenSSL::SSL::SSLSocket.new(sock1, ctx1)
- th = Thread.new do
- begin
- rv = s1.connect_nonblock(exception: false)
- case rv
- when :wait_writable
- IO.select(nil, [s1], nil, 5)
- when :wait_readable
- IO.select([s1], nil, nil, 5)
- end
- end until rv == s1
- end
- accepted = s2.accept
+ ctx2 = OpenSSL::SSL::SSLContext.new
+ ctx2.ciphers = "ECDH"
+ ctx2.ecdh_curves = "P-256:P-384"
+ s2 = OpenSSL::SSL::SSLSocket.new(sock2, ctx2)
- assert called, 'ecdh callback should be called'
- rescue OpenSSL::SSL::SSLError => e
- if e.message =~ /no cipher match/
- skip "ECDH cipher not supported."
- else
- raise e
+ th = Thread.new { s1.accept }
+ s2.connect
+
+ assert s2.cipher[0].start_with?("AECDH"), "AECDH should be used"
+ if s2.respond_to?(:tmp_key)
+ assert_equal "secp384r1", s2.tmp_key.group.curve_name
end
ensure
th.join if th
@@ -385,7 +446,6 @@ module OpenSSL::TestPairM
s2.close if s2
sock1.close if sock1
sock2.close if sock2
- accepted.close if accepted.respond_to?(:close)
end
def test_connect_accept_nonblock_no_exception
@@ -488,36 +548,36 @@ module OpenSSL::TestPairM
end
end
-class OpenSSL::TestEOF1 < Test::Unit::TestCase
+class OpenSSL::TestEOF1 < OpenSSL::TestCase
include TestEOF
include OpenSSL::SSLPair
include OpenSSL::TestEOF1M
end
-class OpenSSL::TestEOF1LowlevelSocket < Test::Unit::TestCase
+class OpenSSL::TestEOF1LowlevelSocket < OpenSSL::TestCase
include TestEOF
include OpenSSL::SSLPairLowlevelSocket
include OpenSSL::TestEOF1M
end
-class OpenSSL::TestEOF2 < Test::Unit::TestCase
+class OpenSSL::TestEOF2 < OpenSSL::TestCase
include TestEOF
include OpenSSL::SSLPair
include OpenSSL::TestEOF2M
end
-class OpenSSL::TestEOF2LowlevelSocket < Test::Unit::TestCase
+class OpenSSL::TestEOF2LowlevelSocket < OpenSSL::TestCase
include TestEOF
include OpenSSL::SSLPairLowlevelSocket
include OpenSSL::TestEOF2M
end
-class OpenSSL::TestPair < Test::Unit::TestCase
+class OpenSSL::TestPair < OpenSSL::TestCase
include OpenSSL::SSLPair
include OpenSSL::TestPairM
end
-class OpenSSL::TestPairLowlevelSocket < Test::Unit::TestCase
+class OpenSSL::TestPairLowlevelSocket < OpenSSL::TestCase
include OpenSSL::SSLPairLowlevelSocket
include OpenSSL::TestPairM
end
diff --git a/test/test_pkcs12.rb b/test/test_pkcs12.rb
index ba07d767..61fb4474 100644
--- a/test/test_pkcs12.rb
+++ b/test/test_pkcs12.rb
@@ -4,7 +4,7 @@ require_relative "utils"
if defined?(OpenSSL::TestUtils)
module OpenSSL
- class TestPKCS12 < Test::Unit::TestCase
+ class TestPKCS12 < OpenSSL::TestCase
include OpenSSL::TestUtils
def setup
diff --git a/test/test_pkcs5.rb b/test/test_pkcs5.rb
index f38fd716..ad8132c2 100644
--- a/test/test_pkcs5.rb
+++ b/test/test_pkcs5.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: false
require_relative 'utils'
-class OpenSSL::TestPKCS5 < Test::Unit::TestCase
+class OpenSSL::TestPKCS5 < OpenSSL::TestCase
def test_pbkdf2_hmac_sha1_rfc6070_c_1_len_20
p ="password"
diff --git a/test/test_pkcs7.rb b/test/test_pkcs7.rb
index ce99db50..def4910c 100644
--- a/test/test_pkcs7.rb
+++ b/test/test_pkcs7.rb
@@ -3,7 +3,7 @@ require_relative 'utils'
if defined?(OpenSSL::TestUtils)
-class OpenSSL::TestPKCS7 < Test::Unit::TestCase
+class OpenSSL::TestPKCS7 < OpenSSL::TestCase
def setup
@rsa1024 = OpenSSL::TestUtils::TEST_KEY_RSA1024
@rsa2048 = OpenSSL::TestUtils::TEST_KEY_RSA2048
@@ -123,12 +123,6 @@ class OpenSSL::TestPKCS7 < Test::Unit::TestCase
end
def test_enveloped
- if OpenSSL::OPENSSL_VERSION_NUMBER <= 0x0090704f
- # PKCS7_encrypt() of OpenSSL-0.9.7d goes to SEGV.
- # http://www.mail-archive.com/openssl-dev@openssl.org/msg17376.html
- return
- end
-
certs = [@ee1_cert, @ee2_cert]
cipher = OpenSSL::Cipher::AES.new("128-CBC")
data = "aaaaa\nbbbbb\nccccc\n"
diff --git a/test/test_pkey_dh.rb b/test/test_pkey_dh.rb
index a0eca53c..afd7a318 100644
--- a/test/test_pkey_dh.rb
+++ b/test/test_pkey_dh.rb
@@ -3,7 +3,7 @@ require_relative 'utils'
if defined?(OpenSSL::TestUtils)
-class OpenSSL::TestPKeyDH < Test::Unit::TestCase
+class OpenSSL::TestPKeyDH < OpenSSL::TestCase
NEW_KEYLEN = 256
diff --git a/test/test_pkey_dsa.rb b/test/test_pkey_dsa.rb
index eb3e4f1c..680a1239 100644
--- a/test/test_pkey_dsa.rb
+++ b/test/test_pkey_dsa.rb
@@ -4,7 +4,7 @@ require 'base64'
if defined?(OpenSSL::TestUtils)
-class OpenSSL::TestPKeyDSA < Test::Unit::TestCase
+class OpenSSL::TestPKeyDSA < OpenSSL::TestCase
def test_private
key = OpenSSL::PKey::DSA.new(256)
assert(key.private?)
@@ -20,7 +20,6 @@ class OpenSSL::TestPKeyDSA < Test::Unit::TestCase
key = OpenSSL::PKey::DSA.new 256
pem = key.public_key.to_pem
OpenSSL::PKey::DSA.new pem
- assert_equal([], OpenSSL.errors)
end
def test_new_break
@@ -84,7 +83,6 @@ end
assert_equal(g, key.g)
assert_equal(y, key.pub_key)
assert_equal(nil, key.priv_key)
- assert_equal([], OpenSSL.errors)
end
def test_read_DSAPublicKey_pem
@@ -109,7 +107,6 @@ fWLOqqkzFeRrYMDzUpl36XktY6Yq8EJYlW9pCMmBVNy/dQ==
assert_equal(g, key.g)
assert_equal(y, key.pub_key)
assert_equal(nil, key.priv_key)
- assert_equal([], OpenSSL.errors)
end
def test_read_DSA_PUBKEY_pem
@@ -135,7 +132,6 @@ YNMbNw==
assert_equal(g, key.g)
assert_equal(y, key.pub_key)
assert_equal(nil, key.priv_key)
- assert_equal([], OpenSSL.errors)
end
def test_export_format_is_DSA_PUBKEY_pem
@@ -165,7 +161,6 @@ YNMbNw==
pub_key = OpenSSL::ASN1.decode(seq[1].value)
assert_equal(OpenSSL::ASN1::INTEGER, pub_key.tag)
assert_equal(key.pub_key, pub_key.value)
- assert_equal([], OpenSSL.errors)
end
def test_read_private_key_der
@@ -174,7 +169,6 @@ YNMbNw==
key2 = OpenSSL::PKey.read(der)
assert(key2.private?)
assert_equal(der, key2.to_der)
- assert_equal([], OpenSSL.errors)
end
def test_read_private_key_pem
@@ -183,7 +177,6 @@ YNMbNw==
key2 = OpenSSL::PKey.read(pem)
assert(key2.private?)
assert_equal(pem, key2.to_pem)
- assert_equal([], OpenSSL.errors)
end
def test_read_public_key_der
@@ -192,7 +185,6 @@ YNMbNw==
key2 = OpenSSL::PKey.read(der)
assert(!key2.private?)
assert_equal(der, key2.to_der)
- assert_equal([], OpenSSL.errors)
end
def test_read_public_key_pem
@@ -201,7 +193,6 @@ YNMbNw==
key2 = OpenSSL::PKey.read(pem)
assert(!key2.private?)
assert_equal(pem, key2.to_pem)
- assert_equal([], OpenSSL.errors)
end
def test_read_private_key_pem_pw
@@ -216,7 +207,6 @@ YNMbNw==
key2 = OpenSSL::PKey.read(pem, 'secret')
assert(key2.private?)
#omit pem equality check, will be different due to cipher iv
- assert_equal([], OpenSSL.errors)
end
def test_export_password_length
@@ -228,6 +218,18 @@ YNMbNw==
assert(pem)
end
+ def test_export_password_funny
+ key = OpenSSL::TestUtils::TEST_KEY_DSA256
+ pem = key.export(OpenSSL::Cipher.new('AES-128-CBC'), "pass\0wd")
+ assert_raise(ArgumentError) do
+ OpenSSL::PKey.read(pem, "pass")
+ end
+ key2 = OpenSSL::PKey.read(pem, "pass\0wd")
+ assert(key2.private?)
+ key3 = OpenSSL::PKey::DSA.new(pem, "pass\0wd")
+ assert(key3.private?)
+ end
+
private
def check_sign_verify(digest)
diff --git a/test/test_pkey_ec.rb b/test/test_pkey_ec.rb
index fe128fd4..4161e9b0 100644
--- a/test/test_pkey_ec.rb
+++ b/test/test_pkey_ec.rb
@@ -3,7 +3,7 @@ require_relative 'utils'
if defined?(OpenSSL::TestUtils) && defined?(OpenSSL::PKey::EC)
-class OpenSSL::TestEC < Test::Unit::TestCase
+class OpenSSL::TestEC < OpenSSL::TestCase
def setup
@data1 = 'foo'
@data2 = 'bar' * 1000 # data too long for DSA sig
@@ -16,7 +16,7 @@ class OpenSSL::TestEC < Test::Unit::TestCase
group = OpenSSL::PKey::EC::Group.new(curve)
key = OpenSSL::PKey::EC.new(group)
- key.generate_key
+ key.generate_key!
@groups << group
@keys << key
@@ -38,11 +38,32 @@ class OpenSSL::TestEC < Test::Unit::TestCase
end
end
+ def test_generate
+ assert_raise(OpenSSL::PKey::ECError) { OpenSSL::PKey::EC.generate("non-existent") }
+ g = OpenSSL::PKey::EC::Group.new("prime256v1")
+ ec = OpenSSL::PKey::EC.generate(g)
+ assert_equal(true, ec.private?)
+ ec = OpenSSL::PKey::EC.generate("prime256v1")
+ assert_equal(true, ec.private?)
+ end
+
def test_check_key
for key in @keys
- assert_equal(key.check_key, true)
- assert_equal(key.private_key?, true)
- assert_equal(key.public_key?, true)
+ assert_equal(true, key.check_key)
+ assert_equal(true, key.private?)
+ assert_equal(true, key.public?)
+ key2 = OpenSSL::PKey::EC.new(key.group)
+ assert_equal(false, key2.private?)
+ assert_equal(false, key2.public?)
+ key2.public_key = key.public_key
+ assert_equal(false, key2.private?)
+ assert_equal(true, key2.public?)
+ key2.private_key = key.private_key
+ assert_equal(true, key2.private?)
+ assert_equal(true, key2.public?)
+ assert_equal(true, key2.check_key)
+ key2.private_key += 1
+ assert_raise(OpenSSL::PKey::ECError) { key2.check_key }
end
end
@@ -115,7 +136,7 @@ class OpenSSL::TestEC < Test::Unit::TestCase
def test_dh_compute_key
for key in @keys
k = OpenSSL::PKey::EC.new(key.group)
- k.generate_key
+ k.generate_key!
puba = key.public_key
pubb = k.public_key
@@ -131,7 +152,6 @@ class OpenSSL::TestEC < Test::Unit::TestCase
ec2 = OpenSSL::PKey.read(der)
assert(ec2.private_key?)
assert_equal(der, ec2.to_der)
- assert_equal([], OpenSSL.errors)
end
def test_read_private_key_pem
@@ -140,7 +160,6 @@ class OpenSSL::TestEC < Test::Unit::TestCase
ec2 = OpenSSL::PKey.read(pem)
assert(ec2.private_key?)
assert_equal(pem, ec2.to_pem)
- assert_equal([], OpenSSL.errors)
end
def test_read_public_key_der
@@ -151,7 +170,6 @@ class OpenSSL::TestEC < Test::Unit::TestCase
ec3 = OpenSSL::PKey.read(der)
assert(!ec3.private_key?)
assert_equal(der, ec3.to_der)
- assert_equal([], OpenSSL.errors)
end
def test_read_public_key_pem
@@ -162,7 +180,6 @@ class OpenSSL::TestEC < Test::Unit::TestCase
ec3 = OpenSSL::PKey.read(pem)
assert(!ec3.private_key?)
assert_equal(pem, ec3.to_pem)
- assert_equal([], OpenSSL.errors)
end
def test_read_private_key_pem_pw
@@ -177,7 +194,6 @@ class OpenSSL::TestEC < Test::Unit::TestCase
ec2 = OpenSSL::PKey.read(pem, 'secret')
assert(ec2.private_key?)
#omit pem equality check, will be different due to cipher iv
- assert_equal([], OpenSSL.errors)
end
def test_export_password_length
@@ -189,20 +205,57 @@ class OpenSSL::TestEC < Test::Unit::TestCase
assert(pem)
end
+ def test_export_password_funny
+ key = OpenSSL::TestUtils::TEST_KEY_EC_P256V1
+ pem = key.export(OpenSSL::Cipher.new('AES-128-CBC'), "pass\0wd")
+ assert_raise(ArgumentError) do
+ OpenSSL::PKey.read(pem, "pass")
+ end
+ key2 = OpenSSL::PKey.read(pem, "pass\0wd")
+ assert(key2.private_key?)
+ key3 = OpenSSL::PKey::EC.new(pem, "pass\0wd")
+ assert(key3.private_key?)
+ end
+
def test_ec_point_mul
- ec = OpenSSL::TestUtils::TEST_KEY_EC_P256V1
- p1 = ec.public_key
- bn1 = OpenSSL::BN.new('10')
- bn2 = OpenSSL::BN.new('20')
-
- p2 = p1.mul(bn1)
- assert(p1.group == p2.group)
- p2 = p1.mul(bn1, bn2)
- assert(p1.group == p2.group)
- p2 = p1.mul([bn1, bn2], [p1])
- assert(p1.group == p2.group)
- p2 = p1.mul([bn1, bn2], [p1], bn2)
- assert(p1.group == p2.group)
+ begin
+ # y^2 = x^3 + 2x + 2 over F_17
+ # generator is (5, 1)
+ group = OpenSSL::PKey::EC::Group.new(:GFp, 17, 2, 2)
+ gen = OpenSSL::PKey::EC::Point.new(group, OpenSSL::BN.new("040501", 16))
+ group.set_generator(gen, 0, 0)
+
+ # 3 * (6, 3) = (16, 13)
+ point_a = OpenSSL::PKey::EC::Point.new(group, OpenSSL::BN.new("040603", 16))
+ result_a1 = point_a.mul(3.to_bn)
+ assert_equal("04100D", result_a1.to_bn.to_s(16))
+ # 3 * (6, 3) + 3 * (5, 1) = (7, 6)
+ result_a2 = point_a.mul(3.to_bn, 3.to_bn)
+ assert_equal("040706", result_a2.to_bn.to_s(16))
+ # 3 * point_a = 3 * (6, 3) = (16, 13)
+ result_b1 = point_a.mul([3.to_bn], [])
+ assert_equal("04100D", result_b1.to_bn.to_s(16))
+ # 3 * point_a + 2 * point_a = 3 * (6, 3) + 2 * (6, 3) = (7, 11)
+ result_b1 = point_a.mul([3.to_bn, 2.to_bn], [point_a])
+ assert_equal("04070B", result_b1.to_bn.to_s(16))
+ # 3 * point_a + 5 * point_a.group.generator = 3 * (6, 3) + 5 * (5, 1) = (13, 10)
+ result_b1 = point_a.mul([3.to_bn], [], 5)
+ assert_equal("040D0A", result_b1.to_bn.to_s(16))
+ rescue OpenSSL::PKey::EC::Group::Error
+ # CentOS patches OpenSSL to reject curves defined over Fp where p < 256 bits
+ raise if $!.message !~ /unsupported field/
+ end
+
+ p256_key = OpenSSL::TestUtils::TEST_KEY_EC_P256V1
+ p256_g = p256_key.group
+ assert_equal(p256_key.public_key, p256_g.generator.mul(p256_key.private_key))
+
+ # invalid argument
+ point = p256_key.public_key
+ assert_raise(TypeError) { point.mul(nil) }
+ assert_raise(ArgumentError) { point.mul([1.to_bn], [point]) }
+ assert_raise(TypeError) { point.mul([1.to_bn], nil) }
+ assert_raise(TypeError) { point.mul([nil], []) }
end
# test Group: asn1_flag, point_conversion
diff --git a/test/test_pkey_rsa.rb b/test/test_pkey_rsa.rb
index 165b1ec9..c3532f63 100644
--- a/test/test_pkey_rsa.rb
+++ b/test/test_pkey_rsa.rb
@@ -4,7 +4,7 @@ require 'base64'
if defined?(OpenSSL::TestUtils)
-class OpenSSL::TestPKeyRSA < Test::Unit::TestCase
+class OpenSSL::TestPKeyRSA < OpenSSL::TestCase
def test_padding
key = OpenSSL::PKey::RSA.new(512, 3)
@@ -180,7 +180,6 @@ AudJR1JobbIbDJrQu6AXnWh5k/YtAgMBAAE=
assert_equal(nil, key.d)
assert_equal(nil, key.p)
assert_equal(nil, key.q)
- assert_equal([], OpenSSL.errors)
end
def test_read_RSA_PUBKEY_pem
@@ -201,7 +200,6 @@ AwEAAQ==
assert_equal(nil, key.d)
assert_equal(nil, key.p)
assert_equal(nil, key.q)
- assert_equal([], OpenSSL.errors)
end
def test_export_format_is_RSA_PUBKEY
@@ -223,7 +221,6 @@ AwEAAQ==
key = OpenSSL::PKey.read(der)
assert(key.private?)
assert_equal(der, key.to_der)
- assert_equal([], OpenSSL.errors)
end
def test_read_private_key_pem
@@ -231,7 +228,6 @@ AwEAAQ==
key = OpenSSL::PKey.read(pem)
assert(key.private?)
assert_equal(pem, key.to_pem)
- assert_equal([], OpenSSL.errors)
end
def test_read_public_key_der
@@ -239,7 +235,6 @@ AwEAAQ==
key = OpenSSL::PKey.read(der)
assert(!key.private?)
assert_equal(der, key.to_der)
- assert_equal([], OpenSSL.errors)
end
def test_read_public_key_pem
@@ -247,7 +242,6 @@ AwEAAQ==
key = OpenSSL::PKey.read(pem)
assert(!key.private?)
assert_equal(pem, key.to_pem)
- assert_equal([], OpenSSL.errors)
end
def test_read_private_key_pem_pw
@@ -261,7 +255,6 @@ AwEAAQ==
key = OpenSSL::PKey.read(pem, 'secret')
assert(key.private?)
#omit pem equality check, will be different due to cipher iv
- assert_equal([], OpenSSL.errors)
end
def test_read_private_key_pem_pw_exception
@@ -272,7 +265,6 @@ AwEAAQ==
raise RuntimeError
end
end
- assert_equal([], OpenSSL.errors)
end
def test_export_password_length
@@ -284,6 +276,24 @@ AwEAAQ==
assert(pem)
end
+ def test_export_password_funny
+ key = OpenSSL::TestUtils::TEST_KEY_RSA1024
+ # this assertion may fail in the future because of OpenSSL change.
+ # the current upper limit is 1024
+ assert_raise(OpenSSL::OpenSSLError) do
+ key.export(OpenSSL::Cipher.new('AES-128-CBC'), 'secr' * 1024)
+ end
+ # password containing NUL byte
+ pem = key.export(OpenSSL::Cipher.new('AES-128-CBC'), "pass\0wd")
+ assert_raise(ArgumentError) do
+ OpenSSL::PKey.read(pem, "pass")
+ end
+ key2 = OpenSSL::PKey.read(pem, "pass\0wd")
+ assert(key2.private?)
+ key3 = OpenSSL::PKey::RSA.new(pem, "pass\0wd")
+ assert(key3.private?)
+ end
+
private
def check_PUBKEY(asn1, key)
@@ -306,7 +316,6 @@ AwEAAQ==
assert_equal(key.n, pub_key.value[0].value)
assert_equal(OpenSSL::ASN1::INTEGER, pub_key.value[1].tag)
assert_equal(key.e, pub_key.value[1].value)
- assert_equal([], OpenSSL.errors)
end
end
diff --git a/test/test_random.rb b/test/test_random.rb
index 8c69d543..ca8427f7 100644
--- a/test/test_random.rb
+++ b/test/test_random.rb
@@ -1,10 +1,7 @@
# frozen_string_literal: false
-begin
- require "openssl"
-rescue LoadError
-end
+require_relative "utils"
-class OpenSSL::TestRandom < Test::Unit::TestCase
+class OpenSSL::TestRandom < OpenSSL::TestCase
def test_random_bytes
assert_equal("", OpenSSL::Random.random_bytes(0))
assert_equal(12, OpenSSL::Random.random_bytes(12).bytesize)
@@ -14,4 +11,4 @@ class OpenSSL::TestRandom < Test::Unit::TestCase
assert_equal("", OpenSSL::Random.pseudo_bytes(0))
assert_equal(12, OpenSSL::Random.pseudo_bytes(12).bytesize)
end
-end if defined?(OpenSSL::Random)
+end if defined?(OpenSSL::TestCase)
diff --git a/test/test_ssl.rb b/test/test_ssl.rb
index f5ca3e9f..164a6aac 100644
--- a/test/test_ssl.rb
+++ b/test/test_ssl.rb
@@ -752,7 +752,7 @@ class OpenSSL::TestSSL < OpenSSL::SSLTestCase
ctx3 = OpenSSL::SSL::SSLContext.new
ctx3.ciphers = "DH"
- refute_predicate ctx3, :frozen?
+ assert_not_predicate ctx3, :frozen?
ctx2 = OpenSSL::SSL::SSLContext.new
ctx2.ciphers = "DH"
@@ -869,10 +869,8 @@ class OpenSSL::TestSSL < OpenSSL::SSLTestCase
start_server(OpenSSL::SSL::VERIFY_NONE, true, :ctx_proc => ctx_proc, :server_proc => server_proc) do |server, port|
2.times do |i|
ctx = OpenSSL::SSL::SSLContext.new
- if defined?(OpenSSL::SSL::OP_NO_TICKET)
- # disable RFC4507 support
- ctx.options = OpenSSL::SSL::OP_NO_TICKET
- end
+ # disable RFC4507 support
+ ctx.options = OpenSSL::SSL::OP_NO_TICKET
server_connect(port, ctx) { |ssl|
ssl.hostname = (i & 1 == 0) ? 'foo.example.com' : 'bar.example.com'
str = "x" * 100 + "\n"
@@ -1064,7 +1062,9 @@ if OpenSSL::OPENSSL_VERSION_NUMBER >= 0x10002000
end
end
-if OpenSSL::OPENSSL_VERSION_NUMBER > 0x10001000
+if OpenSSL::OPENSSL_VERSION_NUMBER > 0x10001000 &&
+ OpenSSL::SSL::SSLContext.method_defined?(:npn_select_cb)
+ # NPN may be disabled by OpenSSL configure option
def test_npn_protocol_selection_ary
advertised = ["http/1.1", "spdy/2"]
@@ -1167,6 +1167,57 @@ end
}
end
+ def test_close_and_socket_close_while_connecting
+ # test it doesn't cause a segmentation fault
+ ctx = OpenSSL::SSL::SSLContext.new
+ ctx.ciphers = "aNULL"
+
+ sock1, sock2 = socketpair
+ ssl1 = OpenSSL::SSL::SSLSocket.new(sock1, ctx)
+ ssl2 = OpenSSL::SSL::SSLSocket.new(sock2, ctx)
+
+ t = Thread.new { ssl1.connect }
+ ssl2.accept
+
+ ssl1.close
+ sock1.close
+ t.value rescue nil
+ ensure
+ ssl1.close if ssl1
+ ssl2.close if ssl2
+ sock1.close if sock1
+ sock2.close if sock2
+ end
+
+ def test_get_ephemeral_key
+ return unless OpenSSL::SSL::SSLSocket.method_defined?(:tmp_key)
+ pkey = OpenSSL::PKey
+ ciphers = {
+ 'ECDHE-RSA-AES128-SHA' => (pkey::EC if defined?(pkey::EC)),
+ 'DHE-RSA-AES128-SHA' => (pkey::DH if defined?(pkey::DH)),
+ 'AES128-SHA' => nil
+ }
+ conf_proc = Proc.new { |ctx| ctx.ciphers = 'ALL' }
+ start_server(OpenSSL::SSL::VERIFY_NONE, true, :ctx_proc => conf_proc) do |server, port|
+ ciphers.each do |cipher, ephemeral|
+ ctx = OpenSSL::SSL::SSLContext.new
+ begin
+ ctx.ciphers = cipher
+ rescue OpenSSL::SSL::SSLError => e
+ next if /no cipher match/ =~ e.message
+ raise
+ end
+ server_connect(port, ctx) do |ssl|
+ if ephemeral
+ assert_instance_of(ephemeral, ssl.tmp_key)
+ else
+ assert_nil(ssl.tmp_key)
+ end
+ end
+ end
+ end
+ end
+
private
def start_server_version(version, ctx_proc=nil, server_proc=nil, &blk)
diff --git a/test/test_ssl_session.rb b/test/test_ssl_session.rb
index 3294aa7f..cdcab02f 100644
--- a/test/test_ssl_session.rb
+++ b/test/test_ssl_session.rb
@@ -55,16 +55,13 @@ tddwpBAEDjcwMzA5NTYzMTU1MzAwpQMCARM=
session = ssl.session
assert(session == OpenSSL::SSL::Session.new(session.to_pem))
assert(session == OpenSSL::SSL::Session.new(ssl))
- assert_equal(300, session.timeout)
session.timeout = 5
assert_equal(5, session.timeout)
assert_not_nil(session.time)
# SSL_SESSION_time keeps long value so we can't keep nsec fragment.
session.time = t1 = Time.now.to_i
assert_equal(Time.at(t1), session.time)
- if session.respond_to?(:id)
- assert_not_nil(session.id)
- end
+ assert_not_nil(session.id)
pem = session.to_pem
assert_match(/\A-----BEGIN SSL SESSION PARAMETERS-----/, pem)
assert_match(/-----END SSL SESSION PARAMETERS-----\Z/, pem)
@@ -171,10 +168,7 @@ __EOS__
session = ssl.session
if last_session
assert(ssl.session_reused?)
-
- if session.respond_to?(:id)
- assert_equal(session.id, last_session.id)
- end
+ assert_equal(session.id, last_session.id)
assert_equal(session.to_pem, last_session.to_pem)
assert_equal(session.to_der, last_session.to_der)
# Older version of OpenSSL may not be consistent. Look up which versions later.
@@ -247,10 +241,8 @@ __EOS__
10.times do |i|
sock = TCPSocket.new("127.0.0.1", port)
ctx = OpenSSL::SSL::SSLContext.new
- if defined?(OpenSSL::SSL::OP_NO_TICKET)
- # disable RFC4507 support
- ctx.options = OpenSSL::SSL::OP_NO_TICKET
- end
+ # disable RFC4507 support
+ ctx.options = OpenSSL::SSL::OP_NO_TICKET
ssl = OpenSSL::SSL::SSLSocket.new(sock, ctx)
ssl.sync_close = true
ssl.session = first_session if first_session
diff --git a/test/test_x509attr.rb b/test/test_x509attr.rb
new file mode 100644
index 00000000..1ba8a875
--- /dev/null
+++ b/test/test_x509attr.rb
@@ -0,0 +1,56 @@
+# frozen_string_literal: false
+require_relative "utils"
+
+if defined?(OpenSSL::TestUtils)
+
+class OpenSSL::TestX509Attribute < OpenSSL::TestCase
+ def test_new
+ ef = OpenSSL::X509::ExtensionFactory.new
+ val = OpenSSL::ASN1::Set.new([OpenSSL::ASN1::Sequence.new([
+ ef.create_extension("keyUsage", "keyCertSign", true)
+ ])])
+ attr = OpenSSL::X509::Attribute.new("extReq", val)
+ assert_equal("extReq", attr.oid)
+ assert_equal(val.to_der, attr.value.to_der)
+ end
+
+ def test_from_der
+ # oid: challengePassword, values: Set[UTF8String<"abc123">]
+ test_der = "\x30\x15\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x09\x07\x31\x08" \
+ "\x0c\x06\x61\x62\x63\x31\x32\x33".b
+ attr = OpenSSL::X509::Attribute.new(test_der)
+ assert_equal(test_der, attr.to_der)
+ assert_equal("challengePassword", attr.oid)
+ assert_equal("abc123", attr.value.value[0].value)
+ end
+
+ def test_to_der
+ ef = OpenSSL::X509::ExtensionFactory.new
+ val = OpenSSL::ASN1::Set.new([OpenSSL::ASN1::Sequence.new([
+ ef.create_extension("keyUsage", "keyCertSign", true)
+ ])])
+ attr = OpenSSL::X509::Attribute.new("extReq", val)
+ expected = OpenSSL::ASN1::Sequence.new([
+ OpenSSL::ASN1::ObjectId.new("extReq"),
+ val
+ ])
+ assert_equal(expected.to_der, attr.to_der)
+ end
+
+ def test_invalid_value
+ # should not change the original value
+ test_der = "\x30\x15\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x09\x07\x31\x08" \
+ "\x0c\x06\x61\x62\x63\x31\x32\x33".b
+ attr = OpenSSL::X509::Attribute.new(test_der)
+ assert_raise(TypeError) {
+ attr.value = "1234"
+ }
+ assert_equal(test_der, attr.to_der)
+ assert_raise(OpenSSL::X509::AttributeError) {
+ attr.oid = "abc123"
+ }
+ assert_equal(test_der, attr.to_der)
+ end
+end
+
+end
diff --git a/test/test_x509cert.rb b/test/test_x509cert.rb
index 72cb9e60..ae7a0f08 100644
--- a/test/test_x509cert.rb
+++ b/test/test_x509cert.rb
@@ -3,7 +3,7 @@ require_relative "utils"
if defined?(OpenSSL::TestUtils)
-class OpenSSL::TestX509Certificate < Test::Unit::TestCase
+class OpenSSL::TestX509Certificate < OpenSSL::TestCase
def setup
@rsa1024 = OpenSSL::TestUtils::TEST_KEY_RSA1024
@rsa2048 = OpenSSL::TestUtils::TEST_KEY_RSA2048
@@ -14,9 +14,6 @@ class OpenSSL::TestX509Certificate < Test::Unit::TestCase
@ee2 = OpenSSL::X509::Name.parse("/DC=org/DC=ruby-lang/CN=EE2")
end
- def teardown
- end
-
def issue_cert(*args)
OpenSSL::TestUtils.issue_cert(*args)
end
diff --git a/test/test_x509crl.rb b/test/test_x509crl.rb
index 7994ddea..fd66c975 100644
--- a/test/test_x509crl.rb
+++ b/test/test_x509crl.rb
@@ -3,7 +3,7 @@ require_relative "utils"
if defined?(OpenSSL::TestUtils)
-class OpenSSL::TestX509CRL < Test::Unit::TestCase
+class OpenSSL::TestX509CRL < OpenSSL::TestCase
def setup
@rsa1024 = OpenSSL::TestUtils::TEST_KEY_RSA1024
@rsa2048 = OpenSSL::TestUtils::TEST_KEY_RSA2048
@@ -14,9 +14,6 @@ class OpenSSL::TestX509CRL < Test::Unit::TestCase
@ee2 = OpenSSL::X509::Name.parse("/DC=org/DC=ruby-lang/CN=EE2")
end
- def teardown
- end
-
def issue_crl(*args)
OpenSSL::TestUtils.issue_crl(*args)
end
diff --git a/test/test_x509ext.rb b/test/test_x509ext.rb
index e6d49bb6..99e2eda5 100644
--- a/test/test_x509ext.rb
+++ b/test/test_x509ext.rb
@@ -3,7 +3,7 @@ require_relative 'utils'
if defined?(OpenSSL::TestUtils)
-class OpenSSL::TestX509Extension < Test::Unit::TestCase
+class OpenSSL::TestX509Extension < OpenSSL::TestCase
def setup
@basic_constraints_value = OpenSSL::ASN1::Sequence([
OpenSSL::ASN1::Boolean(true), # CA
@@ -16,9 +16,6 @@ class OpenSSL::TestX509Extension < Test::Unit::TestCase
])
end
- def teardown
- end
-
def test_new
ext = OpenSSL::X509::Extension.new(@basic_constraints.to_der)
assert_equal("basicConstraints", ext.oid)
diff --git a/test/test_x509name.rb b/test/test_x509name.rb
index 56e79879..d26174ef 100644
--- a/test/test_x509name.rb
+++ b/test/test_x509name.rb
@@ -4,7 +4,7 @@ require_relative 'utils'
if defined?(OpenSSL::TestUtils)
-class OpenSSL::TestX509Name < Test::Unit::TestCase
+class OpenSSL::TestX509Name < OpenSSL::TestCase
OpenSSL::ASN1::ObjectId.register(
"1.2.840.113549.1.9.1", "emailAddress", "emailAddress")
OpenSSL::ASN1::ObjectId.register(
@@ -15,9 +15,6 @@ class OpenSSL::TestX509Name < Test::Unit::TestCase
@obj_type_tmpl.update(OpenSSL::X509::Name::OBJECT_TYPE_TEMPLATE)
end
- def teardown
- end
-
def test_s_new
dn = [ ["C", "JP"], ["O", "example"], ["CN", "www.example.jp"] ]
name = OpenSSL::X509::Name.new(dn)
diff --git a/test/test_x509req.rb b/test/test_x509req.rb
index ee2347b5..c473b47a 100644
--- a/test/test_x509req.rb
+++ b/test/test_x509req.rb
@@ -3,7 +3,7 @@ require_relative "utils"
if defined?(OpenSSL::TestUtils)
-class OpenSSL::TestX509Request < Test::Unit::TestCase
+class OpenSSL::TestX509Request < OpenSSL::TestCase
def setup
@rsa1024 = OpenSSL::TestUtils::TEST_KEY_RSA1024
@rsa2048 = OpenSSL::TestUtils::TEST_KEY_RSA2048
diff --git a/test/test_x509store.rb b/test/test_x509store.rb
index 9964cc8f..8dee1679 100644
--- a/test/test_x509store.rb
+++ b/test/test_x509store.rb
@@ -3,7 +3,7 @@ require_relative "utils"
if defined?(OpenSSL::TestUtils)
-class OpenSSL::TestX509Store < Test::Unit::TestCase
+class OpenSSL::TestX509Store < OpenSSL::TestCase
def setup
@rsa1024 = OpenSSL::TestUtils::TEST_KEY_RSA1024
@rsa2048 = OpenSSL::TestUtils::TEST_KEY_RSA2048
@@ -15,9 +15,6 @@ class OpenSSL::TestX509Store < Test::Unit::TestCase
@ee2 = OpenSSL::X509::Name.parse("/DC=org/DC=ruby-lang/CN=EE2")
end
- def teardown
- end
-
def test_nosegv_on_cleanup
cert = OpenSSL::X509::Certificate.new
store = OpenSSL::X509::Store.new
@@ -151,8 +148,6 @@ class OpenSSL::TestX509Store < Test::Unit::TestCase
assert_equal(false, store.verify(OpenSSL::X509::Certificate.new(ee1_cert)))
assert_equal(OpenSSL::X509::V_ERR_CERT_NOT_YET_VALID, store.error)
- return unless defined?(OpenSSL::X509::V_FLAG_CRL_CHECK)
-
store = OpenSSL::X509::Store.new
store.purpose = OpenSSL::X509::PURPOSE_ANY
store.flags = OpenSSL::X509::V_FLAG_CRL_CHECK
diff --git a/test/utils.rb b/test/utils.rb
index 2e9b7395..b6cf6377 100644
--- a/test/utils.rb
+++ b/test/utils.rb
@@ -182,7 +182,14 @@ AQjjxMXhwULlmuR/K+WwlaZPiLIBYalLAZQ7ZbOPeVkJ8ePao0eLAgEC
end
end
- class OpenSSL::SSLTestCase < Test::Unit::TestCase
+ class OpenSSL::TestCase < Test::Unit::TestCase
+ def teardown
+ # OpenSSL error stack must be empty
+ assert_equal([], OpenSSL.errors)
+ end
+ end
+
+ class OpenSSL::SSLTestCase < OpenSSL::TestCase
RUBY = EnvUtil.rubybin
ITERATIONS = ($0 == __FILE__) ? 100 : 10
@@ -207,9 +214,6 @@ AQjjxMXhwULlmuR/K+WwlaZPiLIBYalLAZQ7ZbOPeVkJ8ePao0eLAgEC
@server = nil
end
- def teardown
- end
-
def issue_cert(*arg)
OpenSSL::TestUtils.issue_cert(*arg)
end
@@ -278,6 +282,7 @@ AQjjxMXhwULlmuR/K+WwlaZPiLIBYalLAZQ7ZbOPeVkJ8ePao0eLAgEC
ctx.cert = @svr_cert
ctx.key = @svr_key
ctx.tmp_dh_callback = proc { OpenSSL::TestUtils::TEST_KEY_DH1024 }
+ ctx.ecdh_curves = "P-256"
ctx.verify_mode = verify_mode
ctx_proc.call(ctx) if ctx_proc