зеркало из https://github.com/github/ruby.git
openssl: import v2.1.0.beta2
Import Ruby/OpenSSL 2.1.0.beta2. The full commit log since commit e72d960db262 which was imported by r60013 can be found at: https://github.com/ruby/openssl/compare/e72d960db262...v2.1.0.beta2 ---------------------------------------------------------------- Kazuki Yamaguchi (26): bn: use ALLOCV() macro instead of xmalloc() appveyor.yml: remove 'openssl version' line test/test_ssl_session: skip tests for session_remove_cb x509ext: implement X509::Extension#== x509attr: implement X509::Attribute#== x509cert: implement X509::Certificate#== x509revoked: add missing X509::Revoked#to_der x509crl, x509revoked: implement X509::{CRL,Revoked}#== x509req: implement X509::Request#== ssl: extract rb_intern("call") cipher: disallow setting AAD for non-AEAD ciphers test/test_cipher: fix test_non_aead_cipher_set_auth_data failure ssl: fix conflict of options in SSLContext#set_params buffering: let #write accept multiple arguments pkey: make pkey_check_public_key() non-static x509cert, x509crl, x509req, ns_spki: check sanity of public key test/envutil: port assert_warning from Ruby trunk test/utils: remove a pointless .public_key call in issue_cert ssl: add SSLContext#add_certificate test/test_ssl: fix test_security_level Drop support for LibreSSL 2.4 kdf: add HKDF support test/test_x509cert: fix flaky test test/test_x509crl: fix random failure History.md: fix a typo Ruby/OpenSSL 2.1.0.beta2 Mark Wright (1): Fix build failure against OpenSSL 1.1 built with no-deprecated Thanks rhenium for the code review and fixes. Peter Karman (1): Add RSA sign_pss() and verify_pss() methods aeris (1): TLS Fallback Signaling Cipher Suite Value kazu (1): Use caller with length to reduce unused strings git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@60907 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
Родитель
55953e374d
Коммит
a55320b093
|
@ -1,18 +1,21 @@
|
|||
Version 2.1.0.beta1
|
||||
Version 2.1.0.beta2
|
||||
===================
|
||||
|
||||
Notable changes
|
||||
---------------
|
||||
|
||||
* Support for OpenSSL versions before 1.0.1 is removed.
|
||||
* Support for OpenSSL versions before 1.0.1 and LibreSSL versions before 2.5
|
||||
is removed.
|
||||
[[GitHub #86]](https://github.com/ruby/openssl/pull/86)
|
||||
* OpenSSL::BN#negative?, #+@, and #-@ are added.
|
||||
* OpenSSL::SSL::SSLSocket#connect raises a more informative exception when
|
||||
certificate verification fails.
|
||||
[[GitHub #99]](https://github.com/ruby/openssl/pull/99)
|
||||
* OpenSSL::KDF module is newly added. Support for scrypt is added.
|
||||
* OpenSSL::KDF module is newly added. In addition to PBKDF2-HMAC that has moved
|
||||
from OpenSSL::PKCS5, scrypt and HKDF are supported.
|
||||
[[GitHub #109]](https://github.com/ruby/openssl/pull/109)
|
||||
* OpenSSL.fips_mode is added. We have had the setter, but not the getter.
|
||||
[[GitHub #173]](https://github.com/ruby/openssl/pull/173)
|
||||
* OpenSSL.fips_mode is added. We had the setter, but not the getter.
|
||||
[[GitHub #125]](https://github.com/ruby/openssl/pull/125)
|
||||
* OpenSSL::OCSP::Request#signed? is added.
|
||||
* OpenSSL::ASN1 handles the indefinite length form better. OpenSSL::ASN1.decode
|
||||
|
@ -22,11 +25,31 @@ Notable changes
|
|||
* OpenSSL::X509::Name#add_entry now accepts two additional keyword arguments
|
||||
'loc' and 'set'.
|
||||
[[GitHub #94]](https://github.com/ruby/openssl/issues/94)
|
||||
* OpenSSL::SSL::SSLContext#min_version= and #max_version= are added.
|
||||
* OpenSSL::SSL::SSLContext#min_version= and #max_version= are added to replace
|
||||
#ssl_version= that was built on top of the deprecated OpenSSL C API. Use of
|
||||
that method and the constant OpenSSL::SSL::SSLContext::METHODS is now
|
||||
deprecated.
|
||||
[[GitHub #142]](https://github.com/ruby/openssl/pull/142)
|
||||
* OpenSSL::X509::Name#to_utf8 is added.
|
||||
[[GitHub #26]](https://github.com/ruby/openssl/issues/26)
|
||||
[[GitHub #143]](https://github.com/ruby/openssl/pull/143)
|
||||
* OpenSSL::X509::{Extension,Attribute,Certificate,CRL,Revoked,Request} can be
|
||||
compared with == operator.
|
||||
[[GitHub #161]](https://github.com/ruby/openssl/pull/161)
|
||||
* TLS Fallback Signaling Cipher Suite Value (SCSV) support is added.
|
||||
[[GitHub #165]](https://github.com/ruby/openssl/pull/165)
|
||||
* Build failure with OpenSSL 1.1 built with no-deprecated is fixed.
|
||||
[[GitHub #160]](https://github.com/ruby/openssl/pull/160)
|
||||
* OpenSSL::Buffering#write accepts an arbitrary number of arguments.
|
||||
[[Feature #9323]](https://bugs.ruby-lang.org/issues/9323)
|
||||
[[GitHub #162]](https://github.com/ruby/openssl/pull/162)
|
||||
* OpenSSL::PKey::RSA#sign_pss and #verify_pss are added. They perform RSA-PSS
|
||||
signature and verification.
|
||||
[[GitHub #75]](https://github.com/ruby/openssl/issues/75)
|
||||
[[GitHub #76]](https://github.com/ruby/openssl/pull/76)
|
||||
[[GitHub #169]](https://github.com/ruby/openssl/pull/169)
|
||||
* OpenSSL::SSL::SSLContext#add_certificate is added.
|
||||
[[GitHub #167]](https://github.com/ruby/openssl/pull/167)
|
||||
|
||||
|
||||
Version 2.0.6
|
||||
|
@ -201,7 +224,7 @@ Notable changes
|
|||
- A new option 'verify_hostname' is added to OpenSSL::SSL::SSLContext. When it
|
||||
is enabled, and the SNI hostname is also set, the hostname verification on
|
||||
the server certificate is automatically performed. It is now enabled by
|
||||
OpenSSL::SSL::Context#set_params.
|
||||
OpenSSL::SSL::SSLContext#set_params.
|
||||
[[GH ruby/openssl#60]](https://github.com/ruby/openssl/pull/60)
|
||||
|
||||
Removals
|
||||
|
|
|
@ -340,9 +340,10 @@ module OpenSSL::Buffering
|
|||
# converted using +.to_s+ method. Returns the number of bytes written.
|
||||
|
||||
def write(*s)
|
||||
s = s.size == 1 ? s[0] : s.join("")
|
||||
do_write(s)
|
||||
s.bytesize
|
||||
s.inject(0) do |written, str|
|
||||
do_write(str)
|
||||
written + str.bytesize
|
||||
end
|
||||
end
|
||||
|
||||
##
|
||||
|
|
|
@ -41,6 +41,11 @@ module OpenSSL
|
|||
end
|
||||
|
||||
class Extension
|
||||
def ==(other)
|
||||
return false unless Extension === other
|
||||
to_der == other.to_der
|
||||
end
|
||||
|
||||
def to_s # "oid = critical, value"
|
||||
str = self.oid
|
||||
str << " = "
|
||||
|
@ -160,6 +165,13 @@ module OpenSSL
|
|||
end
|
||||
end
|
||||
|
||||
class Attribute
|
||||
def ==(other)
|
||||
return false unless Attribute === other
|
||||
to_der == other.to_der
|
||||
end
|
||||
end
|
||||
|
||||
class StoreContext
|
||||
def cleanup
|
||||
warn "(#{caller.first}) OpenSSL::X509::StoreContext#cleanup is deprecated with no replacement" if $VERBOSE
|
||||
|
@ -178,5 +190,26 @@ module OpenSSL
|
|||
}
|
||||
end
|
||||
end
|
||||
|
||||
class CRL
|
||||
def ==(other)
|
||||
return false unless CRL === other
|
||||
to_der == other.to_der
|
||||
end
|
||||
end
|
||||
|
||||
class Revoked
|
||||
def ==(other)
|
||||
return false unless Revoked === other
|
||||
to_der == other.to_der
|
||||
end
|
||||
end
|
||||
|
||||
class Request
|
||||
def ==(other)
|
||||
return false unless Request === other
|
||||
to_der == other.to_der
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,16 +1,16 @@
|
|||
# -*- encoding: utf-8 -*-
|
||||
# stub: openssl 2.1.0.beta1 ruby lib
|
||||
# stub: openssl 2.1.0.beta2 ruby lib
|
||||
# stub: ext/openssl/extconf.rb
|
||||
|
||||
Gem::Specification.new do |s|
|
||||
s.name = "openssl".freeze
|
||||
s.version = "2.1.0.beta1"
|
||||
s.version = "2.1.0.beta2"
|
||||
|
||||
s.required_rubygems_version = Gem::Requirement.new("> 1.3.1".freeze) if s.respond_to? :required_rubygems_version=
|
||||
s.metadata = { "msys2_mingw_dependencies" => "openssl" } if s.respond_to? :metadata=
|
||||
s.require_paths = ["lib".freeze]
|
||||
s.authors = ["Martin Bosslet".freeze, "SHIBATA Hiroshi".freeze, "Zachary Scott".freeze, "Kazuki Yamaguchi".freeze]
|
||||
s.date = "2017-09-24"
|
||||
s.date = "2017-11-25"
|
||||
s.description = "It wraps the OpenSSL library.".freeze
|
||||
s.email = ["ruby-core@ruby-lang.org".freeze]
|
||||
s.extensions = ["ext/openssl/extconf.rb".freeze]
|
||||
|
@ -20,7 +20,7 @@ Gem::Specification.new do |s|
|
|||
s.licenses = ["Ruby".freeze]
|
||||
s.rdoc_options = ["--main".freeze, "README.md".freeze]
|
||||
s.required_ruby_version = Gem::Requirement.new(">= 2.3.0".freeze)
|
||||
s.rubygems_version = "2.6.13".freeze
|
||||
s.rubygems_version = "2.7.2".freeze
|
||||
s.summary = "OpenSSL provides SSL, TLS and general purpose cryptography.".freeze
|
||||
|
||||
if s.respond_to? :specification_version then
|
||||
|
|
|
@ -209,6 +209,10 @@ IMPL_PKEY_GETTER(EC_KEY, ec)
|
|||
# define X509_get0_notAfter(x) X509_get_notAfter(x)
|
||||
# define X509_CRL_get0_lastUpdate(x) X509_CRL_get_lastUpdate(x)
|
||||
# define X509_CRL_get0_nextUpdate(x) X509_CRL_get_nextUpdate(x)
|
||||
# define X509_set1_notBefore(x, t) X509_set_notBefore(x, t)
|
||||
# define X509_set1_notAfter(x, t) X509_set_notAfter(x, t)
|
||||
# define X509_CRL_set1_lastUpdate(x, t) X509_CRL_set_lastUpdate(x, t)
|
||||
# define X509_CRL_set1_nextUpdate(x, t) X509_CRL_set_nextUpdate(x, t)
|
||||
#endif
|
||||
|
||||
#if !defined(HAVE_SSL_SESSION_GET_PROTOCOL_VERSION)
|
||||
|
|
|
@ -1109,25 +1109,14 @@ Init_openssl(void)
|
|||
/*
|
||||
* Init all digests, ciphers
|
||||
*/
|
||||
/* CRYPTO_malloc_init(); */
|
||||
/* ENGINE_load_builtin_engines(); */
|
||||
#if !defined(LIBRESSL_VERSION_NUMBER) && OPENSSL_VERSION_NUMBER >= 0x10100000
|
||||
if (!OPENSSL_init_ssl(0, NULL))
|
||||
rb_raise(rb_eRuntimeError, "OPENSSL_init_ssl");
|
||||
#else
|
||||
OpenSSL_add_ssl_algorithms();
|
||||
OpenSSL_add_all_algorithms();
|
||||
ERR_load_crypto_strings();
|
||||
SSL_load_error_strings();
|
||||
|
||||
/*
|
||||
* FIXME:
|
||||
* On unload do:
|
||||
*/
|
||||
#if 0
|
||||
CONF_modules_unload(1);
|
||||
destroy_ui_method();
|
||||
EVP_cleanup();
|
||||
ENGINE_cleanup();
|
||||
CRYPTO_cleanup_all_ex_data();
|
||||
ERR_remove_state(0);
|
||||
ERR_free_strings();
|
||||
#endif
|
||||
|
||||
/*
|
||||
|
@ -1149,7 +1138,11 @@ Init_openssl(void)
|
|||
/*
|
||||
* Version of OpenSSL the ruby OpenSSL extension is running with
|
||||
*/
|
||||
#if !defined(LIBRESSL_VERSION_NUMBER) && OPENSSL_VERSION_NUMBER >= 0x10100000
|
||||
rb_define_const(mOSSL, "OPENSSL_LIBRARY_VERSION", rb_str_new2(OpenSSL_version(OPENSSL_VERSION)));
|
||||
#else
|
||||
rb_define_const(mOSSL, "OPENSSL_LIBRARY_VERSION", rb_str_new2(SSLeay_version(SSLEAY_VERSION)));
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Version number of OpenSSL the ruby OpenSSL extension was built with
|
||||
|
|
|
@ -35,6 +35,11 @@
|
|||
#if !defined(OPENSSL_NO_OCSP)
|
||||
# include <openssl/ocsp.h>
|
||||
#endif
|
||||
#include <openssl/bn.h>
|
||||
#include <openssl/rsa.h>
|
||||
#include <openssl/dsa.h>
|
||||
#include <openssl/evp.h>
|
||||
#include <openssl/dh.h>
|
||||
|
||||
/*
|
||||
* Common Module
|
||||
|
|
|
@ -979,20 +979,20 @@ static VALUE
|
|||
ossl_bn_hash(VALUE self)
|
||||
{
|
||||
BIGNUM *bn;
|
||||
VALUE hash;
|
||||
VALUE tmp, hash;
|
||||
unsigned char *buf;
|
||||
int len;
|
||||
|
||||
GetBN(self, bn);
|
||||
len = BN_num_bytes(bn);
|
||||
buf = xmalloc(len);
|
||||
buf = ALLOCV(tmp, len);
|
||||
if (BN_bn2bin(bn, buf) != len) {
|
||||
xfree(buf);
|
||||
ossl_raise(eBNError, NULL);
|
||||
ALLOCV_END(tmp);
|
||||
ossl_raise(eBNError, "BN_bn2bin");
|
||||
}
|
||||
|
||||
hash = ST2FIX(rb_memhash(buf, len));
|
||||
xfree(buf);
|
||||
ALLOCV_END(tmp);
|
||||
|
||||
return hash;
|
||||
}
|
||||
|
|
|
@ -508,7 +508,7 @@ ossl_cipher_set_iv(VALUE self, VALUE iv)
|
|||
StringValue(iv);
|
||||
GetCipher(self, ctx);
|
||||
|
||||
if (EVP_CIPHER_CTX_flags(ctx) & EVP_CIPH_FLAG_AEAD_CIPHER)
|
||||
if (EVP_CIPHER_flags(EVP_CIPHER_CTX_cipher(ctx)) & EVP_CIPH_FLAG_AEAD_CIPHER)
|
||||
iv_len = (int)(VALUE)EVP_CIPHER_CTX_get_app_data(ctx);
|
||||
if (!iv_len)
|
||||
iv_len = EVP_CIPHER_CTX_iv_length(ctx);
|
||||
|
@ -535,7 +535,7 @@ ossl_cipher_is_authenticated(VALUE self)
|
|||
|
||||
GetCipher(self, ctx);
|
||||
|
||||
return (EVP_CIPHER_CTX_flags(ctx) & EVP_CIPH_FLAG_AEAD_CIPHER) ? Qtrue : Qfalse;
|
||||
return (EVP_CIPHER_flags(EVP_CIPHER_CTX_cipher(ctx)) & EVP_CIPH_FLAG_AEAD_CIPHER) ? Qtrue : Qfalse;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -569,6 +569,8 @@ ossl_cipher_set_auth_data(VALUE self, VALUE data)
|
|||
in_len = RSTRING_LEN(data);
|
||||
|
||||
GetCipher(self, ctx);
|
||||
if (!(EVP_CIPHER_flags(EVP_CIPHER_CTX_cipher(ctx)) & EVP_CIPH_FLAG_AEAD_CIPHER))
|
||||
ossl_raise(eCipherError, "AEAD not supported by this cipher");
|
||||
|
||||
if (!ossl_cipher_update_long(ctx, NULL, &out_len, in, in_len))
|
||||
ossl_raise(eCipherError, "couldn't set additional authenticated data");
|
||||
|
@ -606,7 +608,7 @@ ossl_cipher_get_auth_tag(int argc, VALUE *argv, VALUE self)
|
|||
|
||||
GetCipher(self, ctx);
|
||||
|
||||
if (!(EVP_CIPHER_CTX_flags(ctx) & EVP_CIPH_FLAG_AEAD_CIPHER))
|
||||
if (!(EVP_CIPHER_flags(EVP_CIPHER_CTX_cipher(ctx)) & EVP_CIPH_FLAG_AEAD_CIPHER))
|
||||
ossl_raise(eCipherError, "authentication tag not supported by this cipher");
|
||||
|
||||
ret = rb_str_new(NULL, tag_len);
|
||||
|
@ -641,7 +643,7 @@ ossl_cipher_set_auth_tag(VALUE self, VALUE vtag)
|
|||
tag_len = RSTRING_LENINT(vtag);
|
||||
|
||||
GetCipher(self, ctx);
|
||||
if (!(EVP_CIPHER_CTX_flags(ctx) & EVP_CIPH_FLAG_AEAD_CIPHER))
|
||||
if (!(EVP_CIPHER_flags(EVP_CIPHER_CTX_cipher(ctx)) & EVP_CIPH_FLAG_AEAD_CIPHER))
|
||||
ossl_raise(eCipherError, "authentication tag not supported by this cipher");
|
||||
|
||||
if (!EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_TAG, tag_len, tag))
|
||||
|
@ -668,7 +670,7 @@ ossl_cipher_set_auth_tag_len(VALUE self, VALUE vlen)
|
|||
EVP_CIPHER_CTX *ctx;
|
||||
|
||||
GetCipher(self, ctx);
|
||||
if (!(EVP_CIPHER_CTX_flags(ctx) & EVP_CIPH_FLAG_AEAD_CIPHER))
|
||||
if (!(EVP_CIPHER_flags(EVP_CIPHER_CTX_cipher(ctx)) & EVP_CIPH_FLAG_AEAD_CIPHER))
|
||||
ossl_raise(eCipherError, "AEAD not supported by this cipher");
|
||||
|
||||
if (!EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_TAG, tag_len, NULL))
|
||||
|
@ -695,7 +697,7 @@ ossl_cipher_set_iv_length(VALUE self, VALUE iv_length)
|
|||
EVP_CIPHER_CTX *ctx;
|
||||
|
||||
GetCipher(self, ctx);
|
||||
if (!(EVP_CIPHER_CTX_flags(ctx) & EVP_CIPH_FLAG_AEAD_CIPHER))
|
||||
if (!(EVP_CIPHER_flags(EVP_CIPHER_CTX_cipher(ctx)) & EVP_CIPH_FLAG_AEAD_CIPHER))
|
||||
ossl_raise(eCipherError, "cipher does not support AEAD");
|
||||
|
||||
if (!EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_IVLEN, len, NULL))
|
||||
|
@ -786,7 +788,7 @@ ossl_cipher_iv_length(VALUE self)
|
|||
int len = 0;
|
||||
|
||||
GetCipher(self, ctx);
|
||||
if (EVP_CIPHER_CTX_flags(ctx) & EVP_CIPH_FLAG_AEAD_CIPHER)
|
||||
if (EVP_CIPHER_flags(EVP_CIPHER_CTX_cipher(ctx)) & EVP_CIPH_FLAG_AEAD_CIPHER)
|
||||
len = (int)(VALUE)EVP_CIPHER_CTX_get_app_data(ctx);
|
||||
if (!len)
|
||||
len = EVP_CIPHER_CTX_iv_length(ctx);
|
||||
|
|
|
@ -46,13 +46,25 @@ VALUE eEngineError;
|
|||
/*
|
||||
* Private
|
||||
*/
|
||||
#define OSSL_ENGINE_LOAD_IF_MATCH(x) \
|
||||
#if !defined(LIBRESSL_VERSION_NUMBER) && OPENSSL_VERSION_NUMBER >= 0x10100000
|
||||
#define OSSL_ENGINE_LOAD_IF_MATCH(engine_name, x) \
|
||||
do{\
|
||||
if(!strcmp(#x, RSTRING_PTR(name))){\
|
||||
ENGINE_load_##x();\
|
||||
if(!strcmp(#engine_name, RSTRING_PTR(name))){\
|
||||
if (OPENSSL_init_crypto(OPENSSL_INIT_ENGINE_##x, NULL))\
|
||||
return Qtrue;\
|
||||
else\
|
||||
ossl_raise(eEngineError, "OPENSSL_init_crypto"); \
|
||||
}\
|
||||
}while(0)
|
||||
#else
|
||||
#define OSSL_ENGINE_LOAD_IF_MATCH(engine_name, x) \
|
||||
do{\
|
||||
if(!strcmp(#engine_name, RSTRING_PTR(name))){\
|
||||
ENGINE_load_##engine_name();\
|
||||
return Qtrue;\
|
||||
}\
|
||||
}while(0)
|
||||
#endif
|
||||
|
||||
static void
|
||||
ossl_engine_free(void *engine)
|
||||
|
@ -94,55 +106,55 @@ ossl_engine_s_load(int argc, VALUE *argv, VALUE klass)
|
|||
StringValueCStr(name);
|
||||
#ifndef OPENSSL_NO_STATIC_ENGINE
|
||||
#if HAVE_ENGINE_LOAD_DYNAMIC
|
||||
OSSL_ENGINE_LOAD_IF_MATCH(dynamic);
|
||||
OSSL_ENGINE_LOAD_IF_MATCH(dynamic, DYNAMIC);
|
||||
#endif
|
||||
#if HAVE_ENGINE_LOAD_4758CCA
|
||||
OSSL_ENGINE_LOAD_IF_MATCH(4758cca);
|
||||
OSSL_ENGINE_LOAD_IF_MATCH(4758cca, 4758CCA);
|
||||
#endif
|
||||
#if HAVE_ENGINE_LOAD_AEP
|
||||
OSSL_ENGINE_LOAD_IF_MATCH(aep);
|
||||
OSSL_ENGINE_LOAD_IF_MATCH(aep, AEP);
|
||||
#endif
|
||||
#if HAVE_ENGINE_LOAD_ATALLA
|
||||
OSSL_ENGINE_LOAD_IF_MATCH(atalla);
|
||||
OSSL_ENGINE_LOAD_IF_MATCH(atalla, ATALLA);
|
||||
#endif
|
||||
#if HAVE_ENGINE_LOAD_CHIL
|
||||
OSSL_ENGINE_LOAD_IF_MATCH(chil);
|
||||
OSSL_ENGINE_LOAD_IF_MATCH(chil, CHIL);
|
||||
#endif
|
||||
#if HAVE_ENGINE_LOAD_CSWIFT
|
||||
OSSL_ENGINE_LOAD_IF_MATCH(cswift);
|
||||
OSSL_ENGINE_LOAD_IF_MATCH(cswift, CSWIFT);
|
||||
#endif
|
||||
#if HAVE_ENGINE_LOAD_NURON
|
||||
OSSL_ENGINE_LOAD_IF_MATCH(nuron);
|
||||
OSSL_ENGINE_LOAD_IF_MATCH(nuron, NURON);
|
||||
#endif
|
||||
#if HAVE_ENGINE_LOAD_SUREWARE
|
||||
OSSL_ENGINE_LOAD_IF_MATCH(sureware);
|
||||
OSSL_ENGINE_LOAD_IF_MATCH(sureware, SUREWARE);
|
||||
#endif
|
||||
#if HAVE_ENGINE_LOAD_UBSEC
|
||||
OSSL_ENGINE_LOAD_IF_MATCH(ubsec);
|
||||
OSSL_ENGINE_LOAD_IF_MATCH(ubsec, UBSEC);
|
||||
#endif
|
||||
#if HAVE_ENGINE_LOAD_PADLOCK
|
||||
OSSL_ENGINE_LOAD_IF_MATCH(padlock);
|
||||
OSSL_ENGINE_LOAD_IF_MATCH(padlock, PADLOCK);
|
||||
#endif
|
||||
#if HAVE_ENGINE_LOAD_CAPI
|
||||
OSSL_ENGINE_LOAD_IF_MATCH(capi);
|
||||
OSSL_ENGINE_LOAD_IF_MATCH(capi, CAPI);
|
||||
#endif
|
||||
#if HAVE_ENGINE_LOAD_GMP
|
||||
OSSL_ENGINE_LOAD_IF_MATCH(gmp);
|
||||
OSSL_ENGINE_LOAD_IF_MATCH(gmp, GMP);
|
||||
#endif
|
||||
#if HAVE_ENGINE_LOAD_GOST
|
||||
OSSL_ENGINE_LOAD_IF_MATCH(gost);
|
||||
OSSL_ENGINE_LOAD_IF_MATCH(gost, GOST);
|
||||
#endif
|
||||
#if HAVE_ENGINE_LOAD_CRYPTODEV
|
||||
OSSL_ENGINE_LOAD_IF_MATCH(cryptodev);
|
||||
OSSL_ENGINE_LOAD_IF_MATCH(cryptodev, CRYPTODEV);
|
||||
#endif
|
||||
#if HAVE_ENGINE_LOAD_AESNI
|
||||
OSSL_ENGINE_LOAD_IF_MATCH(aesni);
|
||||
OSSL_ENGINE_LOAD_IF_MATCH(aesni, AESNI);
|
||||
#endif
|
||||
#endif
|
||||
#ifdef HAVE_ENGINE_LOAD_OPENBSD_DEV_CRYPTO
|
||||
OSSL_ENGINE_LOAD_IF_MATCH(openbsd_dev_crypto);
|
||||
OSSL_ENGINE_LOAD_IF_MATCH(openbsd_dev_crypto, OPENBSD_DEV_CRYPTO);
|
||||
#endif
|
||||
OSSL_ENGINE_LOAD_IF_MATCH(openssl);
|
||||
OSSL_ENGINE_LOAD_IF_MATCH(openssl, OPENSSL);
|
||||
rb_warning("no such builtin loader for `%"PRIsVALUE"'", name);
|
||||
return Qnil;
|
||||
#endif /* HAVE_ENGINE_LOAD_BUILTIN_ENGINES */
|
||||
|
@ -160,7 +172,9 @@ ossl_engine_s_load(int argc, VALUE *argv, VALUE klass)
|
|||
static VALUE
|
||||
ossl_engine_s_cleanup(VALUE self)
|
||||
{
|
||||
#if defined(LIBRESSL_VERSION_NUMBER) || OPENSSL_VERSION_NUMBER < 0x10100000
|
||||
ENGINE_cleanup();
|
||||
#endif
|
||||
return Qnil;
|
||||
}
|
||||
|
||||
|
|
|
@ -3,6 +3,9 @@
|
|||
* Copyright (C) 2007, 2017 Ruby/OpenSSL Project Authors
|
||||
*/
|
||||
#include "ossl.h"
|
||||
#if OPENSSL_VERSION_NUMBER >= 0x10100000 && !defined(LIBRESSL_VERSION_NUMBER)
|
||||
# include <openssl/kdf.h>
|
||||
#endif
|
||||
|
||||
static VALUE mKDF, eKDF;
|
||||
|
||||
|
@ -138,6 +141,97 @@ kdf_scrypt(int argc, VALUE *argv, VALUE self)
|
|||
}
|
||||
#endif
|
||||
|
||||
#if OPENSSL_VERSION_NUMBER >= 0x10100000 && !defined(LIBRESSL_VERSION_NUMBER)
|
||||
/*
|
||||
* call-seq:
|
||||
* KDF.hkdf(ikm, salt:, info:, length:, hash:) -> String
|
||||
*
|
||||
* HMAC-based Extract-and-Expand Key Derivation Function (HKDF) as specified in
|
||||
* {RFC 5869}[https://tools.ietf.org/html/rfc5869].
|
||||
*
|
||||
* New in OpenSSL 1.1.0.
|
||||
*
|
||||
* === Parameters
|
||||
* _ikm_::
|
||||
* The input keying material.
|
||||
* _salt_::
|
||||
* The salt.
|
||||
* _info_::
|
||||
* The context and application specific information.
|
||||
* _length_::
|
||||
* The output length in octets. Must be <= <tt>255 * HashLen</tt>, where
|
||||
* HashLen is the length of the hash function output in octets.
|
||||
* _hash_::
|
||||
* The hash function.
|
||||
*/
|
||||
static VALUE
|
||||
kdf_hkdf(int argc, VALUE *argv, VALUE self)
|
||||
{
|
||||
VALUE ikm, salt, info, opts, kwargs[4], str;
|
||||
static ID kwargs_ids[4];
|
||||
int saltlen, ikmlen, infolen;
|
||||
size_t len;
|
||||
const EVP_MD *md;
|
||||
EVP_PKEY_CTX *pctx;
|
||||
|
||||
if (!kwargs_ids[0]) {
|
||||
kwargs_ids[0] = rb_intern_const("salt");
|
||||
kwargs_ids[1] = rb_intern_const("info");
|
||||
kwargs_ids[2] = rb_intern_const("length");
|
||||
kwargs_ids[3] = rb_intern_const("hash");
|
||||
}
|
||||
rb_scan_args(argc, argv, "1:", &ikm, &opts);
|
||||
rb_get_kwargs(opts, kwargs_ids, 4, 0, kwargs);
|
||||
|
||||
StringValue(ikm);
|
||||
ikmlen = RSTRING_LENINT(ikm);
|
||||
salt = StringValue(kwargs[0]);
|
||||
saltlen = RSTRING_LENINT(salt);
|
||||
info = StringValue(kwargs[1]);
|
||||
infolen = RSTRING_LENINT(info);
|
||||
len = (size_t)NUM2LONG(kwargs[2]);
|
||||
if (len > LONG_MAX)
|
||||
rb_raise(rb_eArgError, "length must be non-negative");
|
||||
md = ossl_evp_get_digestbyname(kwargs[3]);
|
||||
|
||||
str = rb_str_new(NULL, (long)len);
|
||||
pctx = EVP_PKEY_CTX_new_id(EVP_PKEY_HKDF, NULL);
|
||||
if (!pctx)
|
||||
ossl_raise(eKDF, "EVP_PKEY_CTX_new_id");
|
||||
if (EVP_PKEY_derive_init(pctx) <= 0) {
|
||||
EVP_PKEY_CTX_free(pctx);
|
||||
ossl_raise(eKDF, "EVP_PKEY_derive_init");
|
||||
}
|
||||
if (EVP_PKEY_CTX_set_hkdf_md(pctx, md) <= 0) {
|
||||
EVP_PKEY_CTX_free(pctx);
|
||||
ossl_raise(eKDF, "EVP_PKEY_CTX_set_hkdf_md");
|
||||
}
|
||||
if (EVP_PKEY_CTX_set1_hkdf_salt(pctx, (unsigned char *)RSTRING_PTR(salt),
|
||||
saltlen) <= 0) {
|
||||
EVP_PKEY_CTX_free(pctx);
|
||||
ossl_raise(eKDF, "EVP_PKEY_CTX_set_hkdf_salt");
|
||||
}
|
||||
if (EVP_PKEY_CTX_set1_hkdf_key(pctx, (unsigned char *)RSTRING_PTR(ikm),
|
||||
ikmlen) <= 0) {
|
||||
EVP_PKEY_CTX_free(pctx);
|
||||
ossl_raise(eKDF, "EVP_PKEY_CTX_set_hkdf_key");
|
||||
}
|
||||
if (EVP_PKEY_CTX_add1_hkdf_info(pctx, (unsigned char *)RSTRING_PTR(info),
|
||||
infolen) <= 0) {
|
||||
EVP_PKEY_CTX_free(pctx);
|
||||
ossl_raise(eKDF, "EVP_PKEY_CTX_set_hkdf_info");
|
||||
}
|
||||
if (EVP_PKEY_derive(pctx, (unsigned char *)RSTRING_PTR(str), &len) <= 0) {
|
||||
EVP_PKEY_CTX_free(pctx);
|
||||
ossl_raise(eKDF, "EVP_PKEY_derive");
|
||||
}
|
||||
rb_str_set_len(str, (long)len);
|
||||
EVP_PKEY_CTX_free(pctx);
|
||||
|
||||
return str;
|
||||
}
|
||||
#endif
|
||||
|
||||
void
|
||||
Init_ossl_kdf(void)
|
||||
{
|
||||
|
@ -162,6 +256,7 @@ Init_ossl_kdf(void)
|
|||
* * PKCS #5 PBKDF2 (Password-Based Key Derivation Function 2) in
|
||||
* combination with HMAC
|
||||
* * scrypt
|
||||
* * HKDF
|
||||
*
|
||||
* == Examples
|
||||
* === Generating a 128 bit key for a Cipher (e.g. AES)
|
||||
|
@ -218,4 +313,7 @@ Init_ossl_kdf(void)
|
|||
#if defined(HAVE_EVP_PBE_SCRYPT)
|
||||
rb_define_module_function(mKDF, "scrypt", kdf_scrypt, -1);
|
||||
#endif
|
||||
#if OPENSSL_VERSION_NUMBER >= 0x10100000 && !defined(LIBRESSL_VERSION_NUMBER)
|
||||
rb_define_module_function(mKDF, "hkdf", kdf_hkdf, -1);
|
||||
#endif
|
||||
}
|
||||
|
|
|
@ -208,12 +208,13 @@ static VALUE
|
|||
ossl_spki_set_public_key(VALUE self, VALUE key)
|
||||
{
|
||||
NETSCAPE_SPKI *spki;
|
||||
EVP_PKEY *pkey;
|
||||
|
||||
GetSPKI(self, spki);
|
||||
if (!NETSCAPE_SPKI_set_pubkey(spki, GetPKeyPtr(key))) { /* NO NEED TO DUP */
|
||||
ossl_raise(eSPKIError, NULL);
|
||||
}
|
||||
|
||||
pkey = GetPKeyPtr(key);
|
||||
ossl_pkey_check_public_key(pkey);
|
||||
if (!NETSCAPE_SPKI_set_pubkey(spki, pkey))
|
||||
ossl_raise(eSPKIError, "NETSCAPE_SPKI_set_pubkey");
|
||||
return key;
|
||||
}
|
||||
|
||||
|
@ -307,17 +308,20 @@ static VALUE
|
|||
ossl_spki_verify(VALUE self, VALUE key)
|
||||
{
|
||||
NETSCAPE_SPKI *spki;
|
||||
EVP_PKEY *pkey;
|
||||
|
||||
GetSPKI(self, spki);
|
||||
switch (NETSCAPE_SPKI_verify(spki, GetPKeyPtr(key))) { /* NO NEED TO DUP */
|
||||
case 0:
|
||||
pkey = GetPKeyPtr(key);
|
||||
ossl_pkey_check_public_key(pkey);
|
||||
switch (NETSCAPE_SPKI_verify(spki, pkey)) {
|
||||
case 0:
|
||||
ossl_clear_error();
|
||||
return Qfalse;
|
||||
case 1:
|
||||
case 1:
|
||||
return Qtrue;
|
||||
default:
|
||||
ossl_raise(eSPKIError, NULL);
|
||||
default:
|
||||
ossl_raise(eSPKIError, "NETSCAPE_SPKI_verify");
|
||||
}
|
||||
return Qnil; /* dummy */
|
||||
}
|
||||
|
||||
/* Document-class: OpenSSL::Netscape::SPKI
|
||||
|
|
|
@ -163,8 +163,8 @@ ossl_pkey_new_from_data(int argc, VALUE *argv, VALUE self)
|
|||
return ossl_pkey_new(pkey);
|
||||
}
|
||||
|
||||
static void
|
||||
pkey_check_public_key(EVP_PKEY *pkey)
|
||||
void
|
||||
ossl_pkey_check_public_key(const EVP_PKEY *pkey)
|
||||
{
|
||||
void *ptr;
|
||||
const BIGNUM *n, *e, *pubkey;
|
||||
|
@ -172,7 +172,8 @@ pkey_check_public_key(EVP_PKEY *pkey)
|
|||
if (EVP_PKEY_missing_parameters(pkey))
|
||||
ossl_raise(ePKeyError, "parameters missing");
|
||||
|
||||
ptr = EVP_PKEY_get0(pkey);
|
||||
/* OpenSSL < 1.1.0 takes non-const pointer */
|
||||
ptr = EVP_PKEY_get0((EVP_PKEY *)pkey);
|
||||
switch (EVP_PKEY_base_id(pkey)) {
|
||||
case EVP_PKEY_RSA:
|
||||
RSA_get0_key(ptr, &n, &e, NULL);
|
||||
|
@ -352,7 +353,7 @@ ossl_pkey_verify(VALUE self, VALUE digest, VALUE sig, VALUE data)
|
|||
int siglen, result;
|
||||
|
||||
GetPKey(self, pkey);
|
||||
pkey_check_public_key(pkey);
|
||||
ossl_pkey_check_public_key(pkey);
|
||||
md = ossl_evp_get_digestbyname(digest);
|
||||
StringValue(sig);
|
||||
siglen = RSTRING_LENINT(sig);
|
||||
|
|
|
@ -44,6 +44,7 @@ int ossl_generate_cb_2(int p, int n, BN_GENCB *cb);
|
|||
void ossl_generate_cb_stop(void *ptr);
|
||||
|
||||
VALUE ossl_pkey_new(EVP_PKEY *);
|
||||
void ossl_pkey_check_public_key(const EVP_PKEY *);
|
||||
EVP_PKEY *GetPKeyPtr(VALUE);
|
||||
EVP_PKEY *DupPKeyPtr(VALUE);
|
||||
EVP_PKEY *GetPrivPKeyPtr(VALUE);
|
||||
|
|
|
@ -536,6 +536,196 @@ ossl_rsa_private_decrypt(int argc, VALUE *argv, VALUE self)
|
|||
return str;
|
||||
}
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* rsa.sign_pss(digest, data, salt_length:, mgf1_hash:) -> String
|
||||
*
|
||||
* Signs _data_ using the Probabilistic Signature Scheme (RSA-PSS) and returns
|
||||
* the calculated signature.
|
||||
*
|
||||
* RSAError will be raised if an error occurs.
|
||||
*
|
||||
* See #verify_pss for the verification operation.
|
||||
*
|
||||
* === Parameters
|
||||
* _digest_::
|
||||
* A String containing the message digest algorithm name.
|
||||
* _data_::
|
||||
* A String. The data to be signed.
|
||||
* _salt_length_::
|
||||
* The length in octets of the salt. Two special values are reserved:
|
||||
* +:digest+ means the digest length, and +:max+ means the maximum possible
|
||||
* length for the combination of the private key and the selected message
|
||||
* digest algorithm.
|
||||
* _mgf1_hash_::
|
||||
* The hash algorithm used in MGF1 (the currently supported mask generation
|
||||
* function (MGF)).
|
||||
*
|
||||
* === Example
|
||||
* data = "Sign me!"
|
||||
* pkey = OpenSSL::PKey::RSA.new(2048)
|
||||
* signature = pkey.sign_pss("SHA256", data, salt_length: :max, mgf1_hash: "SHA256")
|
||||
* pub_key = pkey.public_key
|
||||
* puts pub_key.verify_pss("SHA256", signature, data,
|
||||
* salt_length: :auto, mgf1_hash: "SHA256") # => true
|
||||
*/
|
||||
static VALUE
|
||||
ossl_rsa_sign_pss(int argc, VALUE *argv, VALUE self)
|
||||
{
|
||||
VALUE digest, data, options, kwargs[2], signature;
|
||||
static ID kwargs_ids[2];
|
||||
EVP_PKEY *pkey;
|
||||
EVP_PKEY_CTX *pkey_ctx;
|
||||
const EVP_MD *md, *mgf1md;
|
||||
EVP_MD_CTX *md_ctx;
|
||||
size_t buf_len;
|
||||
int salt_len;
|
||||
|
||||
if (!kwargs_ids[0]) {
|
||||
kwargs_ids[0] = rb_intern_const("salt_length");
|
||||
kwargs_ids[1] = rb_intern_const("mgf1_hash");
|
||||
}
|
||||
rb_scan_args(argc, argv, "2:", &digest, &data, &options);
|
||||
rb_get_kwargs(options, kwargs_ids, 2, 0, kwargs);
|
||||
if (kwargs[0] == ID2SYM(rb_intern("max")))
|
||||
salt_len = -2; /* RSA_PSS_SALTLEN_MAX_SIGN */
|
||||
else if (kwargs[0] == ID2SYM(rb_intern("digest")))
|
||||
salt_len = -1; /* RSA_PSS_SALTLEN_DIGEST */
|
||||
else
|
||||
salt_len = NUM2INT(kwargs[0]);
|
||||
mgf1md = ossl_evp_get_digestbyname(kwargs[1]);
|
||||
|
||||
pkey = GetPrivPKeyPtr(self);
|
||||
buf_len = EVP_PKEY_size(pkey);
|
||||
md = ossl_evp_get_digestbyname(digest);
|
||||
StringValue(data);
|
||||
signature = rb_str_new(NULL, (long)buf_len);
|
||||
|
||||
md_ctx = EVP_MD_CTX_new();
|
||||
if (!md_ctx)
|
||||
goto err;
|
||||
|
||||
if (EVP_DigestSignInit(md_ctx, &pkey_ctx, md, NULL, pkey) != 1)
|
||||
goto err;
|
||||
|
||||
if (EVP_PKEY_CTX_set_rsa_padding(pkey_ctx, RSA_PKCS1_PSS_PADDING) != 1)
|
||||
goto err;
|
||||
|
||||
if (EVP_PKEY_CTX_set_rsa_pss_saltlen(pkey_ctx, salt_len) != 1)
|
||||
goto err;
|
||||
|
||||
if (EVP_PKEY_CTX_set_rsa_mgf1_md(pkey_ctx, mgf1md) != 1)
|
||||
goto err;
|
||||
|
||||
if (EVP_DigestSignUpdate(md_ctx, RSTRING_PTR(data), RSTRING_LEN(data)) != 1)
|
||||
goto err;
|
||||
|
||||
if (EVP_DigestSignFinal(md_ctx, (unsigned char *)RSTRING_PTR(signature), &buf_len) != 1)
|
||||
goto err;
|
||||
|
||||
rb_str_set_len(signature, (long)buf_len);
|
||||
|
||||
EVP_MD_CTX_free(md_ctx);
|
||||
return signature;
|
||||
|
||||
err:
|
||||
EVP_MD_CTX_free(md_ctx);
|
||||
ossl_raise(eRSAError, NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* rsa.verify_pss(digest, signature, data, salt_length:, mgf1_hash:) -> true | false
|
||||
*
|
||||
* Verifies _data_ using the Probabilistic Signature Scheme (RSA-PSS).
|
||||
*
|
||||
* The return value is +true+ if the signature is valid, +false+ otherwise.
|
||||
* RSAError will be raised if an error occurs.
|
||||
*
|
||||
* See #sign_pss for the signing operation and an example code.
|
||||
*
|
||||
* === Parameters
|
||||
* _digest_::
|
||||
* A String containing the message digest algorithm name.
|
||||
* _data_::
|
||||
* A String. The data to be signed.
|
||||
* _salt_length_::
|
||||
* The length in octets of the salt. Two special values are reserved:
|
||||
* +:digest+ means the digest length, and +:auto+ means automatically
|
||||
* determining the length based on the signature.
|
||||
* _mgf1_hash_::
|
||||
* The hash algorithm used in MGF1.
|
||||
*/
|
||||
static VALUE
|
||||
ossl_rsa_verify_pss(int argc, VALUE *argv, VALUE self)
|
||||
{
|
||||
VALUE digest, signature, data, options, kwargs[2];
|
||||
static ID kwargs_ids[2];
|
||||
EVP_PKEY *pkey;
|
||||
EVP_PKEY_CTX *pkey_ctx;
|
||||
const EVP_MD *md, *mgf1md;
|
||||
EVP_MD_CTX *md_ctx;
|
||||
int result, salt_len;
|
||||
|
||||
if (!kwargs_ids[0]) {
|
||||
kwargs_ids[0] = rb_intern_const("salt_length");
|
||||
kwargs_ids[1] = rb_intern_const("mgf1_hash");
|
||||
}
|
||||
rb_scan_args(argc, argv, "3:", &digest, &signature, &data, &options);
|
||||
rb_get_kwargs(options, kwargs_ids, 2, 0, kwargs);
|
||||
if (kwargs[0] == ID2SYM(rb_intern("auto")))
|
||||
salt_len = -2; /* RSA_PSS_SALTLEN_AUTO */
|
||||
else if (kwargs[0] == ID2SYM(rb_intern("digest")))
|
||||
salt_len = -1; /* RSA_PSS_SALTLEN_DIGEST */
|
||||
else
|
||||
salt_len = NUM2INT(kwargs[0]);
|
||||
mgf1md = ossl_evp_get_digestbyname(kwargs[1]);
|
||||
|
||||
GetPKey(self, pkey);
|
||||
md = ossl_evp_get_digestbyname(digest);
|
||||
StringValue(signature);
|
||||
StringValue(data);
|
||||
|
||||
md_ctx = EVP_MD_CTX_new();
|
||||
if (!md_ctx)
|
||||
goto err;
|
||||
|
||||
if (EVP_DigestVerifyInit(md_ctx, &pkey_ctx, md, NULL, pkey) != 1)
|
||||
goto err;
|
||||
|
||||
if (EVP_PKEY_CTX_set_rsa_padding(pkey_ctx, RSA_PKCS1_PSS_PADDING) != 1)
|
||||
goto err;
|
||||
|
||||
if (EVP_PKEY_CTX_set_rsa_pss_saltlen(pkey_ctx, salt_len) != 1)
|
||||
goto err;
|
||||
|
||||
if (EVP_PKEY_CTX_set_rsa_mgf1_md(pkey_ctx, mgf1md) != 1)
|
||||
goto err;
|
||||
|
||||
if (EVP_DigestVerifyUpdate(md_ctx, RSTRING_PTR(data), RSTRING_LEN(data)) != 1)
|
||||
goto err;
|
||||
|
||||
result = EVP_DigestVerifyFinal(md_ctx,
|
||||
(unsigned char *)RSTRING_PTR(signature),
|
||||
RSTRING_LEN(signature));
|
||||
|
||||
switch (result) {
|
||||
case 0:
|
||||
ossl_clear_error();
|
||||
EVP_MD_CTX_free(md_ctx);
|
||||
return Qfalse;
|
||||
case 1:
|
||||
EVP_MD_CTX_free(md_ctx);
|
||||
return Qtrue;
|
||||
default:
|
||||
goto err;
|
||||
}
|
||||
|
||||
err:
|
||||
EVP_MD_CTX_free(md_ctx);
|
||||
ossl_raise(eRSAError, NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* rsa.params => hash
|
||||
|
@ -731,6 +921,8 @@ Init_ossl_rsa(void)
|
|||
rb_define_method(cRSA, "public_decrypt", ossl_rsa_public_decrypt, -1);
|
||||
rb_define_method(cRSA, "private_encrypt", ossl_rsa_private_encrypt, -1);
|
||||
rb_define_method(cRSA, "private_decrypt", ossl_rsa_private_decrypt, -1);
|
||||
rb_define_method(cRSA, "sign_pss", ossl_rsa_sign_pss, -1);
|
||||
rb_define_method(cRSA, "verify_pss", ossl_rsa_verify_pss, -1);
|
||||
|
||||
DEF_OSSL_PKEY_BN(cRSA, rsa, n);
|
||||
DEF_OSSL_PKEY_BN(cRSA, rsa, e);
|
||||
|
|
|
@ -32,7 +32,7 @@ VALUE cSSLSocket;
|
|||
static VALUE eSSLErrorWaitReadable;
|
||||
static VALUE eSSLErrorWaitWritable;
|
||||
|
||||
static ID ID_callback_state, id_tmp_dh_callback, id_tmp_ecdh_callback,
|
||||
static ID id_call, ID_callback_state, id_tmp_dh_callback, id_tmp_ecdh_callback,
|
||||
id_npn_protocols_encoded;
|
||||
static VALUE sym_exception, sym_wait_readable, sym_wait_writable;
|
||||
|
||||
|
@ -205,7 +205,7 @@ ossl_call_client_cert_cb(VALUE obj)
|
|||
if (NIL_P(cb))
|
||||
return Qnil;
|
||||
|
||||
ary = rb_funcall(cb, rb_intern("call"), 1, obj);
|
||||
ary = rb_funcallv(cb, id_call, 1, &obj);
|
||||
Check_Type(ary, T_ARRAY);
|
||||
GetX509CertPtr(cert = rb_ary_entry(ary, 0));
|
||||
GetPrivPKeyPtr(key = rb_ary_entry(ary, 1));
|
||||
|
@ -248,8 +248,8 @@ ossl_call_tmp_dh_callback(struct tmp_dh_callback_args *args)
|
|||
cb = rb_funcall(args->ssl_obj, args->id, 0);
|
||||
if (NIL_P(cb))
|
||||
return NULL;
|
||||
dh = rb_funcall(cb, rb_intern("call"), 3,
|
||||
args->ssl_obj, INT2NUM(args->is_export), INT2NUM(args->keylength));
|
||||
dh = rb_funcall(cb, id_call, 3, args->ssl_obj, INT2NUM(args->is_export),
|
||||
INT2NUM(args->keylength));
|
||||
pkey = GetPKeyPtr(dh);
|
||||
if (EVP_PKEY_base_id(pkey) != args->type)
|
||||
return NULL;
|
||||
|
@ -374,12 +374,12 @@ ossl_call_session_get_cb(VALUE ary)
|
|||
cb = rb_funcall(ssl_obj, rb_intern("session_get_cb"), 0);
|
||||
if (NIL_P(cb)) return Qnil;
|
||||
|
||||
return rb_funcall(cb, rb_intern("call"), 1, ary);
|
||||
return rb_funcallv(cb, id_call, 1, &ary);
|
||||
}
|
||||
|
||||
/* this method is currently only called for servers (in OpenSSL <= 0.9.8e) */
|
||||
static SSL_SESSION *
|
||||
#if OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(LIBRESSL_VERSION_NUMBER)
|
||||
#if OPENSSL_VERSION_NUMBER >= 0x10100000 && !defined(LIBRESSL_VERSION_NUMBER)
|
||||
ossl_sslctx_session_get_cb(SSL *ssl, const unsigned char *buf, int len, int *copy)
|
||||
#else
|
||||
ossl_sslctx_session_get_cb(SSL *ssl, unsigned char *buf, int len, int *copy)
|
||||
|
@ -420,7 +420,7 @@ ossl_call_session_new_cb(VALUE ary)
|
|||
cb = rb_funcall(ssl_obj, rb_intern("session_new_cb"), 0);
|
||||
if (NIL_P(cb)) return Qnil;
|
||||
|
||||
return rb_funcall(cb, rb_intern("call"), 1, ary);
|
||||
return rb_funcallv(cb, id_call, 1, &ary);
|
||||
}
|
||||
|
||||
/* return 1 normal. return 0 removes the session */
|
||||
|
@ -467,7 +467,7 @@ ossl_call_session_remove_cb(VALUE ary)
|
|||
cb = rb_attr_get(sslctx_obj, id_i_session_remove_cb);
|
||||
if (NIL_P(cb)) return Qnil;
|
||||
|
||||
return rb_funcall(cb, rb_intern("call"), 1, ary);
|
||||
return rb_funcallv(cb, id_call, 1, &ary);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -533,7 +533,7 @@ ossl_call_servername_cb(VALUE ary)
|
|||
cb = rb_attr_get(sslctx_obj, id_i_servername_cb);
|
||||
if (NIL_P(cb)) return Qnil;
|
||||
|
||||
ret_obj = rb_funcall(cb, rb_intern("call"), 1, ary);
|
||||
ret_obj = rb_funcallv(cb, id_call, 1, &ary);
|
||||
if (rb_obj_is_kind_of(ret_obj, cSSLContext)) {
|
||||
SSL *ssl;
|
||||
SSL_CTX *ctx2;
|
||||
|
@ -585,7 +585,7 @@ ssl_renegotiation_cb(const SSL *ssl)
|
|||
cb = rb_attr_get(sslctx_obj, id_i_renegotiation_cb);
|
||||
if (NIL_P(cb)) return;
|
||||
|
||||
(void) rb_funcall(cb, rb_intern("call"), 1, ssl_obj);
|
||||
rb_funcallv(cb, id_call, 1, &ssl_obj);
|
||||
}
|
||||
|
||||
#if !defined(OPENSSL_NO_NEXTPROTONEG) || \
|
||||
|
@ -635,7 +635,7 @@ npn_select_cb_common_i(VALUE tmp)
|
|||
in += l;
|
||||
}
|
||||
|
||||
selected = rb_funcall(args->cb, rb_intern("call"), 1, protocols);
|
||||
selected = rb_funcallv(args->cb, id_call, 1, &protocols);
|
||||
StringValue(selected);
|
||||
len = RSTRING_LEN(selected);
|
||||
if (len < 1 || len >= 256) {
|
||||
|
@ -1193,6 +1193,134 @@ ossl_sslctx_set_security_level(VALUE self, VALUE value)
|
|||
return value;
|
||||
}
|
||||
|
||||
#ifdef SSL_MODE_SEND_FALLBACK_SCSV
|
||||
/*
|
||||
* call-seq:
|
||||
* ctx.enable_fallback_scsv() => nil
|
||||
*
|
||||
* Activate TLS_FALLBACK_SCSV for this context.
|
||||
* See RFC 7507.
|
||||
*/
|
||||
static VALUE
|
||||
ossl_sslctx_enable_fallback_scsv(VALUE self)
|
||||
{
|
||||
SSL_CTX *ctx;
|
||||
|
||||
GetSSLCTX(self, ctx);
|
||||
SSL_CTX_set_mode(ctx, SSL_MODE_SEND_FALLBACK_SCSV);
|
||||
|
||||
return Qnil;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* ctx.add_certificate(certiticate, pkey [, extra_certs]) -> self
|
||||
*
|
||||
* Adds a certificate to the context. _pkey_ must be a corresponding private
|
||||
* key with _certificate_.
|
||||
*
|
||||
* Multiple certificates with different public key type can be added by
|
||||
* repeated calls of this method, and OpenSSL will choose the most appropriate
|
||||
* certificate during the handshake.
|
||||
*
|
||||
* #cert=, #key=, and #extra_chain_cert= are old accessor methods for setting
|
||||
* certificate and internally call this method.
|
||||
*
|
||||
* === Parameters
|
||||
* _certificate_::
|
||||
* A certificate. An instance of OpenSSL::X509::Certificate.
|
||||
* _pkey_::
|
||||
* The private key for _certificate_. An instance of OpenSSL::PKey::PKey.
|
||||
* _extra_certs_::
|
||||
* Optional. An array of OpenSSL::X509::Certificate. When sending a
|
||||
* certificate chain, the certificates specified by this are sent following
|
||||
* _certificate_, in the order in the array.
|
||||
*
|
||||
* === Example
|
||||
* rsa_cert = OpenSSL::X509::Certificate.new(...)
|
||||
* rsa_pkey = OpenSSL::PKey.read(...)
|
||||
* ca_intermediate_cert = OpenSSL::X509::Certificate.new(...)
|
||||
* ctx.add_certificate(rsa_cert, rsa_pkey, [ca_intermediate_cert])
|
||||
*
|
||||
* ecdsa_cert = ...
|
||||
* ecdsa_pkey = ...
|
||||
* another_ca_cert = ...
|
||||
* ctx.add_certificate(ecdsa_cert, ecdsa_pkey, [another_ca_cert])
|
||||
*
|
||||
* === Note
|
||||
* OpenSSL before the version 1.0.2 could handle only one extra chain across
|
||||
* all key types. Calling this method discards the chain set previously.
|
||||
*/
|
||||
static VALUE
|
||||
ossl_sslctx_add_certificate(int argc, VALUE *argv, VALUE self)
|
||||
{
|
||||
VALUE cert, key, extra_chain_ary;
|
||||
SSL_CTX *ctx;
|
||||
X509 *x509;
|
||||
STACK_OF(X509) *extra_chain = NULL;
|
||||
EVP_PKEY *pkey, *pub_pkey;
|
||||
|
||||
GetSSLCTX(self, ctx);
|
||||
rb_scan_args(argc, argv, "21", &cert, &key, &extra_chain_ary);
|
||||
rb_check_frozen(self);
|
||||
x509 = GetX509CertPtr(cert);
|
||||
pkey = GetPrivPKeyPtr(key);
|
||||
|
||||
/*
|
||||
* The reference counter is bumped, and decremented immediately.
|
||||
* X509_get0_pubkey() is only available in OpenSSL >= 1.1.0.
|
||||
*/
|
||||
pub_pkey = X509_get_pubkey(x509);
|
||||
EVP_PKEY_free(pub_pkey);
|
||||
if (!pub_pkey)
|
||||
rb_raise(rb_eArgError, "certificate does not contain public key");
|
||||
if (EVP_PKEY_cmp(pub_pkey, pkey) != 1)
|
||||
rb_raise(rb_eArgError, "public key mismatch");
|
||||
|
||||
if (argc >= 3)
|
||||
extra_chain = ossl_x509_ary2sk(extra_chain_ary);
|
||||
|
||||
if (!SSL_CTX_use_certificate(ctx, x509)) {
|
||||
sk_X509_pop_free(extra_chain, X509_free);
|
||||
ossl_raise(eSSLError, "SSL_CTX_use_certificate");
|
||||
}
|
||||
if (!SSL_CTX_use_PrivateKey(ctx, pkey)) {
|
||||
sk_X509_pop_free(extra_chain, X509_free);
|
||||
ossl_raise(eSSLError, "SSL_CTX_use_PrivateKey");
|
||||
}
|
||||
|
||||
if (extra_chain) {
|
||||
#if OPENSSL_VERSION_NUMBER >= 0x10002000 && !defined(LIBRESSL_VERSION_NUMBER)
|
||||
if (!SSL_CTX_set0_chain(ctx, extra_chain)) {
|
||||
sk_X509_pop_free(extra_chain, X509_free);
|
||||
ossl_raise(eSSLError, "SSL_CTX_set0_chain");
|
||||
}
|
||||
#else
|
||||
STACK_OF(X509) *orig_extra_chain;
|
||||
X509 *x509_tmp;
|
||||
|
||||
/* First, clear the existing chain */
|
||||
SSL_CTX_get_extra_chain_certs(ctx, &orig_extra_chain);
|
||||
if (orig_extra_chain && sk_X509_num(orig_extra_chain)) {
|
||||
rb_warning("SSL_CTX_set0_chain() is not available; " \
|
||||
"clearing previously set certificate chain");
|
||||
SSL_CTX_clear_extra_chain_certs(ctx);
|
||||
}
|
||||
while ((x509_tmp = sk_X509_shift(extra_chain))) {
|
||||
/* Transfers ownership */
|
||||
if (!SSL_CTX_add_extra_chain_cert(ctx, x509_tmp)) {
|
||||
X509_free(x509_tmp);
|
||||
sk_X509_pop_free(extra_chain, X509_free);
|
||||
ossl_raise(eSSLError, "SSL_CTX_add_extra_chain_cert");
|
||||
}
|
||||
}
|
||||
sk_X509_free(extra_chain);
|
||||
#endif
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* ctx.session_add(session) -> true | false
|
||||
|
@ -2261,6 +2389,7 @@ Init_ossl_ssl(void)
|
|||
rb_mWaitWritable = rb_define_module_under(rb_cIO, "WaitWritable");
|
||||
#endif
|
||||
|
||||
id_call = rb_intern("call");
|
||||
ID_callback_state = rb_intern("callback_state");
|
||||
|
||||
ossl_ssl_ex_vcb_idx = SSL_get_ex_new_index(0, (void *)"ossl_ssl_ex_vcb_idx", 0, 0, 0);
|
||||
|
@ -2324,11 +2453,17 @@ Init_ossl_ssl(void)
|
|||
|
||||
/*
|
||||
* Context certificate
|
||||
*
|
||||
* The _cert_, _key_, and _extra_chain_cert_ attributes are deprecated.
|
||||
* It is recommended to use #add_certificate instead.
|
||||
*/
|
||||
rb_attr(cSSLContext, rb_intern("cert"), 1, 1, Qfalse);
|
||||
|
||||
/*
|
||||
* Context private key
|
||||
*
|
||||
* The _cert_, _key_, and _extra_chain_cert_ attributes are deprecated.
|
||||
* It is recommended to use #add_certificate instead.
|
||||
*/
|
||||
rb_attr(cSSLContext, rb_intern("key"), 1, 1, Qfalse);
|
||||
|
||||
|
@ -2402,6 +2537,9 @@ Init_ossl_ssl(void)
|
|||
/*
|
||||
* An Array of extra X509 certificates to be added to the certificate
|
||||
* chain.
|
||||
*
|
||||
* The _cert_, _key_, and _extra_chain_cert_ attributes are deprecated.
|
||||
* It is recommended to use #add_certificate instead.
|
||||
*/
|
||||
rb_attr(cSSLContext, rb_intern("extra_chain_cert"), 1, 1, Qfalse);
|
||||
|
||||
|
@ -2561,6 +2699,10 @@ Init_ossl_ssl(void)
|
|||
rb_define_method(cSSLContext, "ecdh_curves=", ossl_sslctx_set_ecdh_curves, 1);
|
||||
rb_define_method(cSSLContext, "security_level", ossl_sslctx_get_security_level, 0);
|
||||
rb_define_method(cSSLContext, "security_level=", ossl_sslctx_set_security_level, 1);
|
||||
#ifdef SSL_MODE_SEND_FALLBACK_SCSV
|
||||
rb_define_method(cSSLContext, "enable_fallback_scsv", ossl_sslctx_enable_fallback_scsv, 0);
|
||||
#endif
|
||||
rb_define_method(cSSLContext, "add_certificate", ossl_sslctx_add_certificate, -1);
|
||||
|
||||
rb_define_method(cSSLContext, "setup", ossl_sslctx_setup, 0);
|
||||
rb_define_alias(cSSLContext, "freeze", "setup");
|
||||
|
|
|
@ -440,7 +440,7 @@ ossl_x509_set_not_before(VALUE self, VALUE time)
|
|||
|
||||
GetX509(self, x509);
|
||||
asn1time = ossl_x509_time_adjust(NULL, time);
|
||||
if (!X509_set_notBefore(x509, asn1time)) {
|
||||
if (!X509_set1_notBefore(x509, asn1time)) {
|
||||
ASN1_TIME_free(asn1time);
|
||||
ossl_raise(eX509CertError, "X509_set_notBefore");
|
||||
}
|
||||
|
@ -479,7 +479,7 @@ ossl_x509_set_not_after(VALUE self, VALUE time)
|
|||
|
||||
GetX509(self, x509);
|
||||
asn1time = ossl_x509_time_adjust(NULL, time);
|
||||
if (!X509_set_notAfter(x509, asn1time)) {
|
||||
if (!X509_set1_notAfter(x509, asn1time)) {
|
||||
ASN1_TIME_free(asn1time);
|
||||
ossl_raise(eX509CertError, "X509_set_notAfter");
|
||||
}
|
||||
|
@ -508,18 +508,19 @@ ossl_x509_get_public_key(VALUE self)
|
|||
|
||||
/*
|
||||
* call-seq:
|
||||
* cert.public_key = key => key
|
||||
* cert.public_key = key
|
||||
*/
|
||||
static VALUE
|
||||
ossl_x509_set_public_key(VALUE self, VALUE key)
|
||||
{
|
||||
X509 *x509;
|
||||
EVP_PKEY *pkey;
|
||||
|
||||
GetX509(self, x509);
|
||||
if (!X509_set_pubkey(x509, GetPKeyPtr(key))) { /* DUPs pkey */
|
||||
ossl_raise(eX509CertError, NULL);
|
||||
}
|
||||
|
||||
pkey = GetPKeyPtr(key);
|
||||
ossl_pkey_check_public_key(pkey);
|
||||
if (!X509_set_pubkey(x509, pkey))
|
||||
ossl_raise(eX509CertError, "X509_set_pubkey");
|
||||
return key;
|
||||
}
|
||||
|
||||
|
@ -557,9 +558,9 @@ ossl_x509_verify(VALUE self, VALUE key)
|
|||
X509 *x509;
|
||||
EVP_PKEY *pkey;
|
||||
|
||||
pkey = GetPKeyPtr(key); /* NO NEED TO DUP */
|
||||
GetX509(self, x509);
|
||||
|
||||
pkey = GetPKeyPtr(key);
|
||||
ossl_pkey_check_public_key(pkey);
|
||||
switch (X509_verify(x509, pkey)) {
|
||||
case 1:
|
||||
return Qtrue;
|
||||
|
@ -683,6 +684,26 @@ ossl_x509_inspect(VALUE self)
|
|||
ossl_x509_get_not_after(self));
|
||||
}
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* cert1 == cert2 -> true | false
|
||||
*
|
||||
* Compares the two certificates. Note that this takes into account all fields,
|
||||
* not just the issuer name and the serial number.
|
||||
*/
|
||||
static VALUE
|
||||
ossl_x509_eq(VALUE self, VALUE other)
|
||||
{
|
||||
X509 *a, *b;
|
||||
|
||||
GetX509(self, a);
|
||||
if (!rb_obj_is_kind_of(other, cX509Cert))
|
||||
return Qfalse;
|
||||
GetX509(other, b);
|
||||
|
||||
return !X509_cmp(a, b) ? Qtrue : Qfalse;
|
||||
}
|
||||
|
||||
/*
|
||||
* INIT
|
||||
*/
|
||||
|
@ -821,4 +842,5 @@ Init_ossl_x509cert(void)
|
|||
rb_define_method(cX509Cert, "extensions=", ossl_x509_set_extensions, 1);
|
||||
rb_define_method(cX509Cert, "add_extension", ossl_x509_add_extension, 1);
|
||||
rb_define_method(cX509Cert, "inspect", ossl_x509_inspect, 0);
|
||||
rb_define_method(cX509Cert, "==", ossl_x509_eq, 1);
|
||||
}
|
||||
|
|
|
@ -226,7 +226,7 @@ ossl_x509crl_set_last_update(VALUE self, VALUE time)
|
|||
|
||||
GetX509CRL(self, crl);
|
||||
asn1time = ossl_x509_time_adjust(NULL, time);
|
||||
if (!X509_CRL_set_lastUpdate(crl, asn1time)) {
|
||||
if (!X509_CRL_set1_lastUpdate(crl, asn1time)) {
|
||||
ASN1_TIME_free(asn1time);
|
||||
ossl_raise(eX509CRLError, "X509_CRL_set_lastUpdate");
|
||||
}
|
||||
|
@ -257,7 +257,7 @@ ossl_x509crl_set_next_update(VALUE self, VALUE time)
|
|||
|
||||
GetX509CRL(self, crl);
|
||||
asn1time = ossl_x509_time_adjust(NULL, time);
|
||||
if (!X509_CRL_set_nextUpdate(crl, asn1time)) {
|
||||
if (!X509_CRL_set1_nextUpdate(crl, asn1time)) {
|
||||
ASN1_TIME_free(asn1time);
|
||||
ossl_raise(eX509CRLError, "X509_CRL_set_nextUpdate");
|
||||
}
|
||||
|
@ -359,9 +359,12 @@ static VALUE
|
|||
ossl_x509crl_verify(VALUE self, VALUE key)
|
||||
{
|
||||
X509_CRL *crl;
|
||||
EVP_PKEY *pkey;
|
||||
|
||||
GetX509CRL(self, crl);
|
||||
switch (X509_CRL_verify(crl, GetPKeyPtr(key))) {
|
||||
pkey = GetPKeyPtr(key);
|
||||
ossl_pkey_check_public_key(pkey);
|
||||
switch (X509_CRL_verify(crl, pkey)) {
|
||||
case 1:
|
||||
return Qtrue;
|
||||
case 0:
|
||||
|
|
|
@ -293,11 +293,10 @@ ossl_x509req_set_public_key(VALUE self, VALUE key)
|
|||
EVP_PKEY *pkey;
|
||||
|
||||
GetX509Req(self, req);
|
||||
pkey = GetPKeyPtr(key); /* NO NEED TO DUP */
|
||||
if (!X509_REQ_set_pubkey(req, pkey)) {
|
||||
ossl_raise(eX509ReqError, NULL);
|
||||
}
|
||||
|
||||
pkey = GetPKeyPtr(key);
|
||||
ossl_pkey_check_public_key(pkey);
|
||||
if (!X509_REQ_set_pubkey(req, pkey))
|
||||
ossl_raise(eX509ReqError, "X509_REQ_set_pubkey");
|
||||
return key;
|
||||
}
|
||||
|
||||
|
@ -328,7 +327,8 @@ ossl_x509req_verify(VALUE self, VALUE key)
|
|||
EVP_PKEY *pkey;
|
||||
|
||||
GetX509Req(self, req);
|
||||
pkey = GetPKeyPtr(key); /* NO NEED TO DUP */
|
||||
pkey = GetPKeyPtr(key);
|
||||
ossl_pkey_check_public_key(pkey);
|
||||
switch (X509_REQ_verify(req, pkey)) {
|
||||
case 1:
|
||||
return Qtrue;
|
||||
|
|
|
@ -249,6 +249,26 @@ ossl_x509revoked_add_extension(VALUE self, VALUE ext)
|
|||
return ext;
|
||||
}
|
||||
|
||||
static VALUE
|
||||
ossl_x509revoked_to_der(VALUE self)
|
||||
{
|
||||
X509_REVOKED *rev;
|
||||
VALUE str;
|
||||
int len;
|
||||
unsigned char *p;
|
||||
|
||||
GetX509Rev(self, rev);
|
||||
len = i2d_X509_REVOKED(rev, NULL);
|
||||
if (len <= 0)
|
||||
ossl_raise(eX509RevError, "i2d_X509_REVOKED");
|
||||
str = rb_str_new(NULL, len);
|
||||
p = (unsigned char *)RSTRING_PTR(str);
|
||||
if (i2d_X509_REVOKED(rev, &p) <= 0)
|
||||
ossl_raise(eX509RevError, "i2d_X509_REVOKED");
|
||||
ossl_str_adjust(str, p);
|
||||
return str;
|
||||
}
|
||||
|
||||
/*
|
||||
* INIT
|
||||
*/
|
||||
|
@ -276,4 +296,5 @@ Init_ossl_x509revoked(void)
|
|||
rb_define_method(cX509Rev, "extensions", ossl_x509revoked_get_extensions, 0);
|
||||
rb_define_method(cX509Rev, "extensions=", ossl_x509revoked_set_extensions, 1);
|
||||
rb_define_method(cX509Rev, "add_extension", ossl_x509revoked_add_extension, 1);
|
||||
rb_define_method(cX509Rev, "to_der", ossl_x509revoked_to_der, 0);
|
||||
}
|
||||
|
|
|
@ -295,6 +295,13 @@ class OpenSSL::TestCipher < OpenSSL::TestCase
|
|||
assert_equal tag1, tag2
|
||||
end
|
||||
|
||||
def test_non_aead_cipher_set_auth_data
|
||||
assert_raise(OpenSSL::Cipher::CipherError) {
|
||||
cipher = OpenSSL::Cipher.new("aes-128-cfb").encrypt
|
||||
cipher.auth_data = "123"
|
||||
}
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def new_encryptor(algo, **kwargs)
|
||||
|
|
|
@ -131,6 +131,48 @@ class OpenSSL::TestKDF < OpenSSL::TestCase
|
|||
assert_equal(expected, OpenSSL::KDF.scrypt(pass, salt: salt, N: n, r: r, p: p, length: dklen))
|
||||
end
|
||||
|
||||
def test_hkdf_rfc5869_test_case_1
|
||||
pend "HKDF is not implemented" unless OpenSSL::KDF.respond_to?(:hkdf) # OpenSSL >= 1.1.0
|
||||
hash = "sha256"
|
||||
ikm = B("0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b")
|
||||
salt = B("000102030405060708090a0b0c")
|
||||
info = B("f0f1f2f3f4f5f6f7f8f9")
|
||||
l = 42
|
||||
|
||||
okm = B("3cb25f25faacd57a90434f64d0362f2a" \
|
||||
"2d2d0a90cf1a5a4c5db02d56ecc4c5bf" \
|
||||
"34007208d5b887185865")
|
||||
assert_equal(okm, OpenSSL::KDF.hkdf(ikm, salt: salt, info: info, length: l, hash: hash))
|
||||
end
|
||||
|
||||
def test_hkdf_rfc5869_test_case_3
|
||||
pend "HKDF is not implemented" unless OpenSSL::KDF.respond_to?(:hkdf) # OpenSSL >= 1.1.0
|
||||
hash = "sha256"
|
||||
ikm = B("0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b")
|
||||
salt = B("")
|
||||
info = B("")
|
||||
l = 42
|
||||
|
||||
okm = B("8da4e775a563c18f715f802a063c5a31" \
|
||||
"b8a11f5c5ee1879ec3454e5f3c738d2d" \
|
||||
"9d201395faa4b61a96c8")
|
||||
assert_equal(okm, OpenSSL::KDF.hkdf(ikm, salt: salt, info: info, length: l, hash: hash))
|
||||
end
|
||||
|
||||
def test_hkdf_rfc5869_test_case_4
|
||||
pend "HKDF is not implemented" unless OpenSSL::KDF.respond_to?(:hkdf) # OpenSSL >= 1.1.0
|
||||
hash = "sha1"
|
||||
ikm = B("0b0b0b0b0b0b0b0b0b0b0b")
|
||||
salt = B("000102030405060708090a0b0c")
|
||||
info = B("f0f1f2f3f4f5f6f7f8f9")
|
||||
l = 42
|
||||
|
||||
okm = B("085a01ea1b10f36933068b56efa5ad81" \
|
||||
"a4f14b822f5b091568a9cdd4f155fda2" \
|
||||
"c22e422478d305f3f896")
|
||||
assert_equal(okm, OpenSSL::KDF.hkdf(ikm, salt: salt, info: info, length: l, hash: hash))
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def B(ary)
|
||||
|
|
|
@ -122,12 +122,12 @@ class OpenSSL::TestOCSP < OpenSSL::TestCase
|
|||
|
||||
assert_equal true, req.verify([@cert], store, OpenSSL::OCSP::NOINTERN)
|
||||
ret = req.verify([@cert], store)
|
||||
if ret || openssl?(1, 0, 2) || libressl?(2, 4, 2)
|
||||
if ret || openssl?(1, 0, 2)
|
||||
assert_equal true, ret
|
||||
else
|
||||
# RT2560; OCSP_request_verify() does not find signer cert from 'certs' when
|
||||
# OCSP_NOINTERN is not specified.
|
||||
# fixed by OpenSSL 1.0.1j, 1.0.2 and LibreSSL 2.4.2
|
||||
# fixed by OpenSSL 1.0.1j, 1.0.2
|
||||
pend "RT2560: ocsp_req_find_signer"
|
||||
end
|
||||
|
||||
|
@ -262,11 +262,6 @@ class OpenSSL::TestOCSP < OpenSSL::TestCase
|
|||
bres.add_status(cid2, OpenSSL::OCSP::V_CERTSTATUS_REVOKED, OpenSSL::OCSP::REVOKED_STATUS_UNSPECIFIED, -400, -300, nil, [])
|
||||
bres.add_status(cid2, OpenSSL::OCSP::V_CERTSTATUS_GOOD, nil, nil, Time.now + 100, nil, nil)
|
||||
|
||||
if bres.responses[2].check_validity # thisUpdate is in future; must fail
|
||||
# LibreSSL bug; skip for now
|
||||
pend "OCSP_check_validity() is broken"
|
||||
end
|
||||
|
||||
single1 = bres.responses[0]
|
||||
assert_equal false, single1.check_validity
|
||||
assert_equal false, single1.check_validity(30)
|
||||
|
@ -275,6 +270,8 @@ class OpenSSL::TestOCSP < OpenSSL::TestCase
|
|||
assert_equal true, single2.check_validity
|
||||
assert_equal true, single2.check_validity(0, 500)
|
||||
assert_equal false, single2.check_validity(0, 200)
|
||||
single3 = bres.responses[2]
|
||||
assert_equal false, single3.check_validity
|
||||
end
|
||||
|
||||
def test_response
|
||||
|
|
|
@ -362,6 +362,15 @@ module OpenSSL::TestPairM
|
|||
}
|
||||
end
|
||||
|
||||
def test_write_multiple_arguments
|
||||
ssl_pair {|s1, s2|
|
||||
str1 = "foo"; str2 = "bar"
|
||||
assert_equal 6, s1.write(str1, str2)
|
||||
s1.close
|
||||
assert_equal "foobar", s2.read
|
||||
}
|
||||
end
|
||||
|
||||
def test_partial_tls_record_read_nonblock
|
||||
ssl_pair { |s1, s2|
|
||||
# the beginning of a TLS record
|
||||
|
|
|
@ -113,6 +113,39 @@ class OpenSSL::TestPKeyRSA < OpenSSL::PKeyTestCase
|
|||
}
|
||||
end
|
||||
|
||||
def test_sign_verify_pss
|
||||
key = Fixtures.pkey("rsa1024")
|
||||
data = "Sign me!"
|
||||
invalid_data = "Sign me?"
|
||||
|
||||
signature = key.sign_pss("SHA256", data, salt_length: 20, mgf1_hash: "SHA1")
|
||||
assert_equal 128, signature.bytesize
|
||||
assert_equal true,
|
||||
key.verify_pss("SHA256", signature, data, salt_length: 20, mgf1_hash: "SHA1")
|
||||
assert_equal true,
|
||||
key.verify_pss("SHA256", signature, data, salt_length: :auto, mgf1_hash: "SHA1")
|
||||
assert_equal false,
|
||||
key.verify_pss("SHA256", signature, invalid_data, salt_length: 20, mgf1_hash: "SHA1")
|
||||
|
||||
signature = key.sign_pss("SHA256", data, salt_length: :digest, mgf1_hash: "SHA1")
|
||||
assert_equal true,
|
||||
key.verify_pss("SHA256", signature, data, salt_length: 32, mgf1_hash: "SHA1")
|
||||
assert_equal true,
|
||||
key.verify_pss("SHA256", signature, data, salt_length: :auto, mgf1_hash: "SHA1")
|
||||
assert_equal false,
|
||||
key.verify_pss("SHA256", signature, data, salt_length: 20, mgf1_hash: "SHA1")
|
||||
|
||||
signature = key.sign_pss("SHA256", data, salt_length: :max, mgf1_hash: "SHA1")
|
||||
assert_equal true,
|
||||
key.verify_pss("SHA256", signature, data, salt_length: 94, mgf1_hash: "SHA1")
|
||||
assert_equal true,
|
||||
key.verify_pss("SHA256", signature, data, salt_length: :auto, mgf1_hash: "SHA1")
|
||||
|
||||
assert_raise(OpenSSL::PKey::RSAError) {
|
||||
key.sign_pss("SHA256", data, salt_length: 95, mgf1_hash: "SHA1")
|
||||
}
|
||||
end
|
||||
|
||||
def test_RSAPrivateKey
|
||||
rsa1024 = Fixtures.pkey("rsa1024")
|
||||
asn1 = OpenSSL::ASN1::Sequence([
|
||||
|
|
|
@ -54,6 +54,87 @@ class OpenSSL::TestSSL < OpenSSL::SSLTestCase
|
|||
}
|
||||
end
|
||||
|
||||
def test_add_certificate
|
||||
ctx_proc = -> ctx {
|
||||
# Unset values set by start_server
|
||||
ctx.cert = ctx.key = ctx.extra_chain_cert = nil
|
||||
ctx.add_certificate(@svr_cert, @svr_key, [@ca_cert]) # RSA
|
||||
}
|
||||
start_server(ctx_proc: ctx_proc) do |port|
|
||||
server_connect(port) { |ssl|
|
||||
assert_equal @svr_cert.subject, ssl.peer_cert.subject
|
||||
assert_equal [@svr_cert.subject, @ca_cert.subject],
|
||||
ssl.peer_cert_chain.map(&:subject)
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
def test_add_certificate_multiple_certs
|
||||
pend "EC is not supported" unless defined?(OpenSSL::PKey::EC)
|
||||
pend "TLS 1.2 is not supported" unless tls12_supported?
|
||||
|
||||
# SSL_CTX_set0_chain() is needed for setting multiple certificate chains
|
||||
add0_chain_supported = openssl?(1, 0, 2)
|
||||
|
||||
if add0_chain_supported
|
||||
ca2_key = Fixtures.pkey("rsa1024")
|
||||
ca2_exts = [
|
||||
["basicConstraints", "CA:TRUE", true],
|
||||
["keyUsage", "cRLSign, keyCertSign", true],
|
||||
]
|
||||
ca2_dn = OpenSSL::X509::Name.parse_rfc2253("CN=CA2")
|
||||
ca2_cert = issue_cert(ca2_dn, ca2_key, 123, ca2_exts, nil, nil)
|
||||
else
|
||||
# Use the same CA as @svr_cert
|
||||
ca2_key = @ca_key; ca2_cert = @ca_cert
|
||||
end
|
||||
|
||||
ecdsa_key = Fixtures.pkey("p256")
|
||||
exts = [
|
||||
["keyUsage", "digitalSignature", false],
|
||||
]
|
||||
ecdsa_dn = OpenSSL::X509::Name.parse_rfc2253("CN=localhost2")
|
||||
ecdsa_cert = issue_cert(ecdsa_dn, ecdsa_key, 456, exts, ca2_cert, ca2_key)
|
||||
|
||||
if !add0_chain_supported
|
||||
# Testing the warning emitted when 'extra' chain is replaced
|
||||
tctx = OpenSSL::SSL::SSLContext.new
|
||||
tctx.add_certificate(@svr_cert, @svr_key, [@ca_cert])
|
||||
assert_warning(/set0_chain/) {
|
||||
tctx.add_certificate(ecdsa_cert, ecdsa_key, [ca2_cert])
|
||||
}
|
||||
end
|
||||
|
||||
ctx_proc = -> ctx {
|
||||
# Unset values set by start_server
|
||||
ctx.cert = ctx.key = ctx.extra_chain_cert = nil
|
||||
ctx.ecdh_curves = "P-256" unless openssl?(1, 0, 2)
|
||||
ctx.add_certificate(@svr_cert, @svr_key, [@ca_cert]) # RSA
|
||||
EnvUtil.suppress_warning do # !add0_chain_supported
|
||||
ctx.add_certificate(ecdsa_cert, ecdsa_key, [ca2_cert])
|
||||
end
|
||||
}
|
||||
start_server(ctx_proc: ctx_proc) do |port|
|
||||
ctx = OpenSSL::SSL::SSLContext.new
|
||||
ctx.max_version = :TLS1_2 # TODO: We need this to force certificate type
|
||||
ctx.ciphers = "aECDSA"
|
||||
server_connect(port, ctx) { |ssl|
|
||||
assert_equal ecdsa_cert.subject, ssl.peer_cert.subject
|
||||
assert_equal [ecdsa_cert.subject, ca2_cert.subject],
|
||||
ssl.peer_cert_chain.map(&:subject)
|
||||
}
|
||||
|
||||
ctx = OpenSSL::SSL::SSLContext.new
|
||||
ctx.max_version = :TLS1_2
|
||||
ctx.ciphers = "aRSA"
|
||||
server_connect(port, ctx) { |ssl|
|
||||
assert_equal @svr_cert.subject, ssl.peer_cert.subject
|
||||
assert_equal [@svr_cert.subject, @ca_cert.subject],
|
||||
ssl.peer_cert_chain.map(&:subject)
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
def test_sysread_and_syswrite
|
||||
start_server { |port|
|
||||
server_connect(port) { |ssl|
|
||||
|
@ -1222,6 +1303,59 @@ end
|
|||
end
|
||||
end
|
||||
|
||||
def test_fallback_scsv
|
||||
pend "Fallback SCSV is not supported" unless OpenSSL::SSL::SSLContext.method_defined?( :enable_fallback_scsv)
|
||||
|
||||
start_server do |port|
|
||||
ctx = OpenSSL::SSL::SSLContext.new
|
||||
ctx.max_version = OpenSSL::SSL::TLS1_2_VERSION
|
||||
# Here is OK
|
||||
# TLS1.2 supported and this is what we ask the first time
|
||||
server_connect(port, ctx)
|
||||
end
|
||||
|
||||
ctx_proc = proc { |ctx|
|
||||
ctx.max_version = OpenSSL::SSL::TLS1_1_VERSION
|
||||
}
|
||||
start_server(ctx_proc: ctx_proc) do |port|
|
||||
ctx = OpenSSL::SSL::SSLContext.new
|
||||
ctx.enable_fallback_scsv
|
||||
ctx.max_version = OpenSSL::SSL::TLS1_1_VERSION
|
||||
# Here is OK too
|
||||
# TLS1.2 not supported, fallback to TLS1.1 and signaling the fallback
|
||||
# Server doesn't support better, so connection OK
|
||||
server_connect(port, ctx)
|
||||
end
|
||||
|
||||
# Here is not OK
|
||||
# TLS1.2 is supported, fallback to TLS1.1 (downgrade attack) and signaling the fallback
|
||||
# Server support better, so refuse the connection
|
||||
sock1, sock2 = socketpair
|
||||
begin
|
||||
ctx1 = OpenSSL::SSL::SSLContext.new
|
||||
s1 = OpenSSL::SSL::SSLSocket.new(sock1, ctx1)
|
||||
|
||||
ctx2 = OpenSSL::SSL::SSLContext.new
|
||||
ctx2.enable_fallback_scsv
|
||||
ctx2.max_version = OpenSSL::SSL::TLS1_1_VERSION
|
||||
s2 = OpenSSL::SSL::SSLSocket.new(sock2, ctx2)
|
||||
t = Thread.new {
|
||||
assert_raise_with_message(OpenSSL::SSL::SSLError, /inappropriate fallback/) {
|
||||
s2.connect
|
||||
}
|
||||
}
|
||||
|
||||
assert_raise_with_message(OpenSSL::SSL::SSLError, /inappropriate fallback/) {
|
||||
s1.accept
|
||||
}
|
||||
|
||||
assert t.join
|
||||
ensure
|
||||
sock1.close
|
||||
sock2.close
|
||||
end
|
||||
end
|
||||
|
||||
def test_dh_callback
|
||||
pend "TLS 1.2 is not supported" unless tls12_supported?
|
||||
|
||||
|
@ -1336,11 +1470,24 @@ end
|
|||
return
|
||||
end
|
||||
assert_equal(1, ctx.security_level)
|
||||
# assert_raise(OpenSSL::SSL::SSLError) { ctx.key = Fixtures.pkey("dsa512") }
|
||||
# ctx.key = Fixtures.pkey("rsa1024")
|
||||
# ctx.security_level = 2
|
||||
# assert_raise(OpenSSL::SSL::SSLError) { ctx.key = Fixtures.pkey("rsa1024") }
|
||||
pend "FIXME: SSLContext#key= currently does not raise because SSL_CTX_use_certificate() is delayed"
|
||||
|
||||
dsa512 = Fixtures.pkey("dsa512")
|
||||
dsa512_cert = issue_cert(@svr, dsa512, 50, [], @ca_cert, @ca_key)
|
||||
rsa1024 = Fixtures.pkey("rsa1024")
|
||||
rsa1024_cert = issue_cert(@svr, rsa1024, 51, [], @ca_cert, @ca_key)
|
||||
|
||||
assert_raise(OpenSSL::SSL::SSLError) {
|
||||
# 512 bit DSA key is rejected because it offers < 80 bits of security
|
||||
ctx.add_certificate(dsa512_cert, dsa512)
|
||||
}
|
||||
assert_nothing_raised {
|
||||
ctx.add_certificate(rsa1024_cert, rsa1024)
|
||||
}
|
||||
ctx.security_level = 2
|
||||
assert_raise(OpenSSL::SSL::SSLError) {
|
||||
# < 112 bits of security
|
||||
ctx.add_certificate(rsa1024_cert, rsa1024)
|
||||
}
|
||||
end
|
||||
|
||||
def test_dup
|
||||
|
|
|
@ -62,6 +62,23 @@ class OpenSSL::TestX509Attribute < OpenSSL::TestCase
|
|||
attr = OpenSSL::X509::Attribute.new("challengePassword", val)
|
||||
assert_equal(attr.to_der, attr.dup.to_der)
|
||||
end
|
||||
|
||||
def test_eq
|
||||
val1 = OpenSSL::ASN1::Set([
|
||||
OpenSSL::ASN1::UTF8String("abc123")
|
||||
])
|
||||
attr1 = OpenSSL::X509::Attribute.new("challengePassword", val1)
|
||||
attr2 = OpenSSL::X509::Attribute.new("challengePassword", val1)
|
||||
ef = OpenSSL::X509::ExtensionFactory.new
|
||||
val2 = OpenSSL::ASN1::Set.new([OpenSSL::ASN1::Sequence.new([
|
||||
ef.create_extension("keyUsage", "keyCertSign", true)
|
||||
])])
|
||||
attr3 = OpenSSL::X509::Attribute.new("extReq", val2)
|
||||
|
||||
assert_equal false, attr1 == 12345
|
||||
assert_equal true, attr1 == attr2
|
||||
assert_equal false, attr1 == attr3
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
|
|
@ -169,6 +169,26 @@ class OpenSSL::TestX509Certificate < OpenSSL::TestCase
|
|||
}
|
||||
end
|
||||
|
||||
def test_eq
|
||||
now = Time.now
|
||||
cacert = issue_cert(@ca, @rsa1024, 1, [], nil, nil,
|
||||
not_before: now, not_after: now + 3600)
|
||||
cert1 = issue_cert(@ee1, @rsa2048, 2, [], cacert, @rsa1024,
|
||||
not_before: now, not_after: now + 3600)
|
||||
cert2 = issue_cert(@ee1, @rsa2048, 2, [], cacert, @rsa1024,
|
||||
not_before: now, not_after: now + 3600)
|
||||
cert3 = issue_cert(@ee1, @rsa2048, 3, [], cacert, @rsa1024,
|
||||
not_before: now, not_after: now + 3600)
|
||||
cert4 = issue_cert(@ee1, @rsa2048, 2, [], cacert, @rsa1024,
|
||||
digest: "sha512", not_before: now, not_after: now + 3600)
|
||||
|
||||
assert_equal false, cert1 == 12345
|
||||
assert_equal true, cert1 == cert2
|
||||
assert_equal false, cert1 == cert3
|
||||
assert_equal false, cert1 == cert4
|
||||
assert_equal false, cert3 == cert4
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def certificate_error_returns_false
|
||||
|
|
|
@ -197,6 +197,58 @@ class OpenSSL::TestX509CRL < OpenSSL::TestCase
|
|||
assert_equal(false, crl.verify(@dsa512))
|
||||
end
|
||||
|
||||
def test_revoked_to_der
|
||||
# revokedCertificates SEQUENCE OF SEQUENCE {
|
||||
# userCertificate CertificateSerialNumber,
|
||||
# revocationDate Time,
|
||||
# crlEntryExtensions Extensions OPTIONAL
|
||||
# -- if present, version MUST be v2
|
||||
# } OPTIONAL,
|
||||
|
||||
now = Time.utc(2000, 1, 1)
|
||||
rev1 = OpenSSL::X509::Revoked.new
|
||||
rev1.serial = 123
|
||||
rev1.time = now
|
||||
ext = OpenSSL::X509::Extension.new("CRLReason", OpenSSL::ASN1::Enumerated(1))
|
||||
rev1.extensions = [ext]
|
||||
asn1 = OpenSSL::ASN1::Sequence([
|
||||
OpenSSL::ASN1::Integer(123),
|
||||
OpenSSL::ASN1::UTCTime(now),
|
||||
OpenSSL::ASN1::Sequence([ext.to_der])
|
||||
])
|
||||
|
||||
assert_equal asn1.to_der, rev1.to_der
|
||||
end
|
||||
|
||||
def test_eq
|
||||
now = Time.now
|
||||
|
||||
cacert = issue_cert(@ca, @rsa1024, 1, [], nil, nil)
|
||||
crl1 = issue_crl([], 1, now, now + 3600, [], cacert, @rsa1024, "sha256")
|
||||
rev1 = OpenSSL::X509::Revoked.new.tap { |rev|
|
||||
rev.serial = 1
|
||||
rev.time = now
|
||||
}
|
||||
crl1.add_revoked(rev1)
|
||||
crl2 = OpenSSL::X509::CRL.new(crl1.to_der)
|
||||
|
||||
# CRL
|
||||
assert_equal false, crl1 == 12345
|
||||
assert_equal true, crl1 == crl2
|
||||
rev2 = OpenSSL::X509::Revoked.new.tap { |rev|
|
||||
rev.serial = 2
|
||||
rev.time = now
|
||||
}
|
||||
crl2.add_revoked(rev2)
|
||||
assert_equal false, crl1 == crl2
|
||||
|
||||
# Revoked
|
||||
assert_equal false, rev1 == 12345
|
||||
assert_equal true, rev1 == crl2.revoked[0]
|
||||
assert_equal false, rev1 == crl2.revoked[1]
|
||||
assert_equal true, rev2 == crl2.revoked[1]
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def crl_error_returns_false
|
||||
|
|
|
@ -75,6 +75,17 @@ class OpenSSL::TestX509Extension < OpenSSL::TestCase
|
|||
assert_equal(@basic_constraints.to_der, ext.to_der)
|
||||
assert_equal(ext.to_der, ext.dup.to_der)
|
||||
end
|
||||
|
||||
def test_eq
|
||||
ext1 = OpenSSL::X509::Extension.new(@basic_constraints.to_der)
|
||||
ef = OpenSSL::X509::ExtensionFactory.new
|
||||
ext2 = ef.create_extension("basicConstraints", "critical, CA:TRUE, pathlen:2")
|
||||
ext3 = ef.create_extension("basicConstraints", "critical, CA:TRUE")
|
||||
|
||||
assert_equal false, ext1 == 12345
|
||||
assert_equal true, ext1 == ext2
|
||||
assert_equal false, ext1 == ext3
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
|
|
@ -141,6 +141,16 @@ class OpenSSL::TestX509Request < OpenSSL::TestCase
|
|||
assert_equal(req.to_der, req.dup.to_der)
|
||||
end
|
||||
|
||||
def test_eq
|
||||
req1 = issue_csr(0, @dn, @rsa1024, "sha1")
|
||||
req2 = issue_csr(0, @dn, @rsa1024, "sha1")
|
||||
req3 = issue_csr(0, @dn, @rsa1024, "sha256")
|
||||
|
||||
assert_equal false, req1 == 12345
|
||||
assert_equal true, req1 == req2
|
||||
assert_equal false, req1 == req3
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def request_error_returns_false
|
||||
|
|
|
@ -67,7 +67,7 @@ module OpenSSL::TestUtils
|
|||
cert.serial = serial
|
||||
cert.subject = dn
|
||||
cert.issuer = issuer.subject
|
||||
cert.public_key = key.public_key
|
||||
cert.public_key = key
|
||||
now = Time.now
|
||||
cert.not_before = not_before || now - 3600
|
||||
cert.not_after = not_after || now + 3600
|
||||
|
|
Загрузка…
Ссылка в новой задаче