mirror of
https://github.com/ruby/ruby.git
synced 2022-11-09 12:17:21 -05:00
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:
e72d960db2
...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:
parent
55953e374d
commit
a55320b093
32 changed files with 1020 additions and 116 deletions
|
@ -1,18 +1,21 @@
|
||||||
Version 2.1.0.beta1
|
Version 2.1.0.beta2
|
||||||
===================
|
===================
|
||||||
|
|
||||||
Notable changes
|
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)
|
[[GitHub #86]](https://github.com/ruby/openssl/pull/86)
|
||||||
* OpenSSL::BN#negative?, #+@, and #-@ are added.
|
* OpenSSL::BN#negative?, #+@, and #-@ are added.
|
||||||
* OpenSSL::SSL::SSLSocket#connect raises a more informative exception when
|
* OpenSSL::SSL::SSLSocket#connect raises a more informative exception when
|
||||||
certificate verification fails.
|
certificate verification fails.
|
||||||
[[GitHub #99]](https://github.com/ruby/openssl/pull/99)
|
[[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)
|
[[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)
|
[[GitHub #125]](https://github.com/ruby/openssl/pull/125)
|
||||||
* OpenSSL::OCSP::Request#signed? is added.
|
* OpenSSL::OCSP::Request#signed? is added.
|
||||||
* OpenSSL::ASN1 handles the indefinite length form better. OpenSSL::ASN1.decode
|
* 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
|
* OpenSSL::X509::Name#add_entry now accepts two additional keyword arguments
|
||||||
'loc' and 'set'.
|
'loc' and 'set'.
|
||||||
[[GitHub #94]](https://github.com/ruby/openssl/issues/94)
|
[[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)
|
[[GitHub #142]](https://github.com/ruby/openssl/pull/142)
|
||||||
* OpenSSL::X509::Name#to_utf8 is added.
|
* OpenSSL::X509::Name#to_utf8 is added.
|
||||||
[[GitHub #26]](https://github.com/ruby/openssl/issues/26)
|
[[GitHub #26]](https://github.com/ruby/openssl/issues/26)
|
||||||
[[GitHub #143]](https://github.com/ruby/openssl/pull/143)
|
[[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
|
Version 2.0.6
|
||||||
|
@ -201,7 +224,7 @@ Notable changes
|
||||||
- A new option 'verify_hostname' is added to OpenSSL::SSL::SSLContext. When it
|
- 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
|
is enabled, and the SNI hostname is also set, the hostname verification on
|
||||||
the server certificate is automatically performed. It is now enabled by
|
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)
|
[[GH ruby/openssl#60]](https://github.com/ruby/openssl/pull/60)
|
||||||
|
|
||||||
Removals
|
Removals
|
||||||
|
|
|
@ -340,9 +340,10 @@ module OpenSSL::Buffering
|
||||||
# converted using +.to_s+ method. Returns the number of bytes written.
|
# converted using +.to_s+ method. Returns the number of bytes written.
|
||||||
|
|
||||||
def write(*s)
|
def write(*s)
|
||||||
s = s.size == 1 ? s[0] : s.join("")
|
s.inject(0) do |written, str|
|
||||||
do_write(s)
|
do_write(str)
|
||||||
s.bytesize
|
written + str.bytesize
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
##
|
##
|
||||||
|
|
|
@ -41,6 +41,11 @@ module OpenSSL
|
||||||
end
|
end
|
||||||
|
|
||||||
class Extension
|
class Extension
|
||||||
|
def ==(other)
|
||||||
|
return false unless Extension === other
|
||||||
|
to_der == other.to_der
|
||||||
|
end
|
||||||
|
|
||||||
def to_s # "oid = critical, value"
|
def to_s # "oid = critical, value"
|
||||||
str = self.oid
|
str = self.oid
|
||||||
str << " = "
|
str << " = "
|
||||||
|
@ -160,6 +165,13 @@ module OpenSSL
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
class Attribute
|
||||||
|
def ==(other)
|
||||||
|
return false unless Attribute === other
|
||||||
|
to_der == other.to_der
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
class StoreContext
|
class StoreContext
|
||||||
def cleanup
|
def cleanup
|
||||||
warn "(#{caller.first}) OpenSSL::X509::StoreContext#cleanup is deprecated with no replacement" if $VERBOSE
|
warn "(#{caller.first}) OpenSSL::X509::StoreContext#cleanup is deprecated with no replacement" if $VERBOSE
|
||||||
|
@ -178,5 +190,26 @@ module OpenSSL
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
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
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,16 +1,16 @@
|
||||||
# -*- encoding: utf-8 -*-
|
# -*- encoding: utf-8 -*-
|
||||||
# stub: openssl 2.1.0.beta1 ruby lib
|
# stub: openssl 2.1.0.beta2 ruby lib
|
||||||
# stub: ext/openssl/extconf.rb
|
# stub: ext/openssl/extconf.rb
|
||||||
|
|
||||||
Gem::Specification.new do |s|
|
Gem::Specification.new do |s|
|
||||||
s.name = "openssl".freeze
|
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.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.metadata = { "msys2_mingw_dependencies" => "openssl" } if s.respond_to? :metadata=
|
||||||
s.require_paths = ["lib".freeze]
|
s.require_paths = ["lib".freeze]
|
||||||
s.authors = ["Martin Bosslet".freeze, "SHIBATA Hiroshi".freeze, "Zachary Scott".freeze, "Kazuki Yamaguchi".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.description = "It wraps the OpenSSL library.".freeze
|
||||||
s.email = ["ruby-core@ruby-lang.org".freeze]
|
s.email = ["ruby-core@ruby-lang.org".freeze]
|
||||||
s.extensions = ["ext/openssl/extconf.rb".freeze]
|
s.extensions = ["ext/openssl/extconf.rb".freeze]
|
||||||
|
@ -20,7 +20,7 @@ Gem::Specification.new do |s|
|
||||||
s.licenses = ["Ruby".freeze]
|
s.licenses = ["Ruby".freeze]
|
||||||
s.rdoc_options = ["--main".freeze, "README.md".freeze]
|
s.rdoc_options = ["--main".freeze, "README.md".freeze]
|
||||||
s.required_ruby_version = Gem::Requirement.new(">= 2.3.0".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
|
s.summary = "OpenSSL provides SSL, TLS and general purpose cryptography.".freeze
|
||||||
|
|
||||||
if s.respond_to? :specification_version then
|
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_get0_notAfter(x) X509_get_notAfter(x)
|
||||||
# define X509_CRL_get0_lastUpdate(x) X509_CRL_get_lastUpdate(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_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
|
#endif
|
||||||
|
|
||||||
#if !defined(HAVE_SSL_SESSION_GET_PROTOCOL_VERSION)
|
#if !defined(HAVE_SSL_SESSION_GET_PROTOCOL_VERSION)
|
||||||
|
|
|
@ -1109,25 +1109,14 @@ Init_openssl(void)
|
||||||
/*
|
/*
|
||||||
* Init all digests, ciphers
|
* Init all digests, ciphers
|
||||||
*/
|
*/
|
||||||
/* CRYPTO_malloc_init(); */
|
#if !defined(LIBRESSL_VERSION_NUMBER) && OPENSSL_VERSION_NUMBER >= 0x10100000
|
||||||
/* ENGINE_load_builtin_engines(); */
|
if (!OPENSSL_init_ssl(0, NULL))
|
||||||
|
rb_raise(rb_eRuntimeError, "OPENSSL_init_ssl");
|
||||||
|
#else
|
||||||
OpenSSL_add_ssl_algorithms();
|
OpenSSL_add_ssl_algorithms();
|
||||||
OpenSSL_add_all_algorithms();
|
OpenSSL_add_all_algorithms();
|
||||||
ERR_load_crypto_strings();
|
ERR_load_crypto_strings();
|
||||||
SSL_load_error_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
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -1149,7 +1138,11 @@ Init_openssl(void)
|
||||||
/*
|
/*
|
||||||
* Version of OpenSSL the ruby OpenSSL extension is running with
|
* 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)));
|
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
|
* Version number of OpenSSL the ruby OpenSSL extension was built with
|
||||||
|
|
|
@ -35,6 +35,11 @@
|
||||||
#if !defined(OPENSSL_NO_OCSP)
|
#if !defined(OPENSSL_NO_OCSP)
|
||||||
# include <openssl/ocsp.h>
|
# include <openssl/ocsp.h>
|
||||||
#endif
|
#endif
|
||||||
|
#include <openssl/bn.h>
|
||||||
|
#include <openssl/rsa.h>
|
||||||
|
#include <openssl/dsa.h>
|
||||||
|
#include <openssl/evp.h>
|
||||||
|
#include <openssl/dh.h>
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Common Module
|
* Common Module
|
||||||
|
|
|
@ -979,20 +979,20 @@ static VALUE
|
||||||
ossl_bn_hash(VALUE self)
|
ossl_bn_hash(VALUE self)
|
||||||
{
|
{
|
||||||
BIGNUM *bn;
|
BIGNUM *bn;
|
||||||
VALUE hash;
|
VALUE tmp, hash;
|
||||||
unsigned char *buf;
|
unsigned char *buf;
|
||||||
int len;
|
int len;
|
||||||
|
|
||||||
GetBN(self, bn);
|
GetBN(self, bn);
|
||||||
len = BN_num_bytes(bn);
|
len = BN_num_bytes(bn);
|
||||||
buf = xmalloc(len);
|
buf = ALLOCV(tmp, len);
|
||||||
if (BN_bn2bin(bn, buf) != len) {
|
if (BN_bn2bin(bn, buf) != len) {
|
||||||
xfree(buf);
|
ALLOCV_END(tmp);
|
||||||
ossl_raise(eBNError, NULL);
|
ossl_raise(eBNError, "BN_bn2bin");
|
||||||
}
|
}
|
||||||
|
|
||||||
hash = ST2FIX(rb_memhash(buf, len));
|
hash = ST2FIX(rb_memhash(buf, len));
|
||||||
xfree(buf);
|
ALLOCV_END(tmp);
|
||||||
|
|
||||||
return hash;
|
return hash;
|
||||||
}
|
}
|
||||||
|
|
|
@ -508,7 +508,7 @@ ossl_cipher_set_iv(VALUE self, VALUE iv)
|
||||||
StringValue(iv);
|
StringValue(iv);
|
||||||
GetCipher(self, 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)
|
||||||
iv_len = (int)(VALUE)EVP_CIPHER_CTX_get_app_data(ctx);
|
iv_len = (int)(VALUE)EVP_CIPHER_CTX_get_app_data(ctx);
|
||||||
if (!iv_len)
|
if (!iv_len)
|
||||||
iv_len = EVP_CIPHER_CTX_iv_length(ctx);
|
iv_len = EVP_CIPHER_CTX_iv_length(ctx);
|
||||||
|
@ -535,7 +535,7 @@ ossl_cipher_is_authenticated(VALUE self)
|
||||||
|
|
||||||
GetCipher(self, ctx);
|
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);
|
in_len = RSTRING_LEN(data);
|
||||||
|
|
||||||
GetCipher(self, ctx);
|
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))
|
if (!ossl_cipher_update_long(ctx, NULL, &out_len, in, in_len))
|
||||||
ossl_raise(eCipherError, "couldn't set additional authenticated data");
|
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);
|
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");
|
ossl_raise(eCipherError, "authentication tag not supported by this cipher");
|
||||||
|
|
||||||
ret = rb_str_new(NULL, tag_len);
|
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);
|
tag_len = RSTRING_LENINT(vtag);
|
||||||
|
|
||||||
GetCipher(self, 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, "authentication tag not supported by this 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))
|
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;
|
EVP_CIPHER_CTX *ctx;
|
||||||
|
|
||||||
GetCipher(self, 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");
|
ossl_raise(eCipherError, "AEAD not supported by this cipher");
|
||||||
|
|
||||||
if (!EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_TAG, tag_len, NULL))
|
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;
|
EVP_CIPHER_CTX *ctx;
|
||||||
|
|
||||||
GetCipher(self, 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");
|
ossl_raise(eCipherError, "cipher does not support AEAD");
|
||||||
|
|
||||||
if (!EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_IVLEN, len, NULL))
|
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;
|
int len = 0;
|
||||||
|
|
||||||
GetCipher(self, 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)
|
||||||
len = (int)(VALUE)EVP_CIPHER_CTX_get_app_data(ctx);
|
len = (int)(VALUE)EVP_CIPHER_CTX_get_app_data(ctx);
|
||||||
if (!len)
|
if (!len)
|
||||||
len = EVP_CIPHER_CTX_iv_length(ctx);
|
len = EVP_CIPHER_CTX_iv_length(ctx);
|
||||||
|
|
|
@ -46,13 +46,25 @@ VALUE eEngineError;
|
||||||
/*
|
/*
|
||||||
* Private
|
* 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{\
|
do{\
|
||||||
if(!strcmp(#x, RSTRING_PTR(name))){\
|
if(!strcmp(#engine_name, RSTRING_PTR(name))){\
|
||||||
ENGINE_load_##x();\
|
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;\
|
return Qtrue;\
|
||||||
}\
|
}\
|
||||||
}while(0)
|
}while(0)
|
||||||
|
#endif
|
||||||
|
|
||||||
static void
|
static void
|
||||||
ossl_engine_free(void *engine)
|
ossl_engine_free(void *engine)
|
||||||
|
@ -94,55 +106,55 @@ ossl_engine_s_load(int argc, VALUE *argv, VALUE klass)
|
||||||
StringValueCStr(name);
|
StringValueCStr(name);
|
||||||
#ifndef OPENSSL_NO_STATIC_ENGINE
|
#ifndef OPENSSL_NO_STATIC_ENGINE
|
||||||
#if HAVE_ENGINE_LOAD_DYNAMIC
|
#if HAVE_ENGINE_LOAD_DYNAMIC
|
||||||
OSSL_ENGINE_LOAD_IF_MATCH(dynamic);
|
OSSL_ENGINE_LOAD_IF_MATCH(dynamic, DYNAMIC);
|
||||||
#endif
|
#endif
|
||||||
#if HAVE_ENGINE_LOAD_4758CCA
|
#if HAVE_ENGINE_LOAD_4758CCA
|
||||||
OSSL_ENGINE_LOAD_IF_MATCH(4758cca);
|
OSSL_ENGINE_LOAD_IF_MATCH(4758cca, 4758CCA);
|
||||||
#endif
|
#endif
|
||||||
#if HAVE_ENGINE_LOAD_AEP
|
#if HAVE_ENGINE_LOAD_AEP
|
||||||
OSSL_ENGINE_LOAD_IF_MATCH(aep);
|
OSSL_ENGINE_LOAD_IF_MATCH(aep, AEP);
|
||||||
#endif
|
#endif
|
||||||
#if HAVE_ENGINE_LOAD_ATALLA
|
#if HAVE_ENGINE_LOAD_ATALLA
|
||||||
OSSL_ENGINE_LOAD_IF_MATCH(atalla);
|
OSSL_ENGINE_LOAD_IF_MATCH(atalla, ATALLA);
|
||||||
#endif
|
#endif
|
||||||
#if HAVE_ENGINE_LOAD_CHIL
|
#if HAVE_ENGINE_LOAD_CHIL
|
||||||
OSSL_ENGINE_LOAD_IF_MATCH(chil);
|
OSSL_ENGINE_LOAD_IF_MATCH(chil, CHIL);
|
||||||
#endif
|
#endif
|
||||||
#if HAVE_ENGINE_LOAD_CSWIFT
|
#if HAVE_ENGINE_LOAD_CSWIFT
|
||||||
OSSL_ENGINE_LOAD_IF_MATCH(cswift);
|
OSSL_ENGINE_LOAD_IF_MATCH(cswift, CSWIFT);
|
||||||
#endif
|
#endif
|
||||||
#if HAVE_ENGINE_LOAD_NURON
|
#if HAVE_ENGINE_LOAD_NURON
|
||||||
OSSL_ENGINE_LOAD_IF_MATCH(nuron);
|
OSSL_ENGINE_LOAD_IF_MATCH(nuron, NURON);
|
||||||
#endif
|
#endif
|
||||||
#if HAVE_ENGINE_LOAD_SUREWARE
|
#if HAVE_ENGINE_LOAD_SUREWARE
|
||||||
OSSL_ENGINE_LOAD_IF_MATCH(sureware);
|
OSSL_ENGINE_LOAD_IF_MATCH(sureware, SUREWARE);
|
||||||
#endif
|
#endif
|
||||||
#if HAVE_ENGINE_LOAD_UBSEC
|
#if HAVE_ENGINE_LOAD_UBSEC
|
||||||
OSSL_ENGINE_LOAD_IF_MATCH(ubsec);
|
OSSL_ENGINE_LOAD_IF_MATCH(ubsec, UBSEC);
|
||||||
#endif
|
#endif
|
||||||
#if HAVE_ENGINE_LOAD_PADLOCK
|
#if HAVE_ENGINE_LOAD_PADLOCK
|
||||||
OSSL_ENGINE_LOAD_IF_MATCH(padlock);
|
OSSL_ENGINE_LOAD_IF_MATCH(padlock, PADLOCK);
|
||||||
#endif
|
#endif
|
||||||
#if HAVE_ENGINE_LOAD_CAPI
|
#if HAVE_ENGINE_LOAD_CAPI
|
||||||
OSSL_ENGINE_LOAD_IF_MATCH(capi);
|
OSSL_ENGINE_LOAD_IF_MATCH(capi, CAPI);
|
||||||
#endif
|
#endif
|
||||||
#if HAVE_ENGINE_LOAD_GMP
|
#if HAVE_ENGINE_LOAD_GMP
|
||||||
OSSL_ENGINE_LOAD_IF_MATCH(gmp);
|
OSSL_ENGINE_LOAD_IF_MATCH(gmp, GMP);
|
||||||
#endif
|
#endif
|
||||||
#if HAVE_ENGINE_LOAD_GOST
|
#if HAVE_ENGINE_LOAD_GOST
|
||||||
OSSL_ENGINE_LOAD_IF_MATCH(gost);
|
OSSL_ENGINE_LOAD_IF_MATCH(gost, GOST);
|
||||||
#endif
|
#endif
|
||||||
#if HAVE_ENGINE_LOAD_CRYPTODEV
|
#if HAVE_ENGINE_LOAD_CRYPTODEV
|
||||||
OSSL_ENGINE_LOAD_IF_MATCH(cryptodev);
|
OSSL_ENGINE_LOAD_IF_MATCH(cryptodev, CRYPTODEV);
|
||||||
#endif
|
#endif
|
||||||
#if HAVE_ENGINE_LOAD_AESNI
|
#if HAVE_ENGINE_LOAD_AESNI
|
||||||
OSSL_ENGINE_LOAD_IF_MATCH(aesni);
|
OSSL_ENGINE_LOAD_IF_MATCH(aesni, AESNI);
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
#ifdef HAVE_ENGINE_LOAD_OPENBSD_DEV_CRYPTO
|
#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
|
#endif
|
||||||
OSSL_ENGINE_LOAD_IF_MATCH(openssl);
|
OSSL_ENGINE_LOAD_IF_MATCH(openssl, OPENSSL);
|
||||||
rb_warning("no such builtin loader for `%"PRIsVALUE"'", name);
|
rb_warning("no such builtin loader for `%"PRIsVALUE"'", name);
|
||||||
return Qnil;
|
return Qnil;
|
||||||
#endif /* HAVE_ENGINE_LOAD_BUILTIN_ENGINES */
|
#endif /* HAVE_ENGINE_LOAD_BUILTIN_ENGINES */
|
||||||
|
@ -160,7 +172,9 @@ ossl_engine_s_load(int argc, VALUE *argv, VALUE klass)
|
||||||
static VALUE
|
static VALUE
|
||||||
ossl_engine_s_cleanup(VALUE self)
|
ossl_engine_s_cleanup(VALUE self)
|
||||||
{
|
{
|
||||||
|
#if defined(LIBRESSL_VERSION_NUMBER) || OPENSSL_VERSION_NUMBER < 0x10100000
|
||||||
ENGINE_cleanup();
|
ENGINE_cleanup();
|
||||||
|
#endif
|
||||||
return Qnil;
|
return Qnil;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3,6 +3,9 @@
|
||||||
* Copyright (C) 2007, 2017 Ruby/OpenSSL Project Authors
|
* Copyright (C) 2007, 2017 Ruby/OpenSSL Project Authors
|
||||||
*/
|
*/
|
||||||
#include "ossl.h"
|
#include "ossl.h"
|
||||||
|
#if OPENSSL_VERSION_NUMBER >= 0x10100000 && !defined(LIBRESSL_VERSION_NUMBER)
|
||||||
|
# include <openssl/kdf.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
static VALUE mKDF, eKDF;
|
static VALUE mKDF, eKDF;
|
||||||
|
|
||||||
|
@ -138,6 +141,97 @@ kdf_scrypt(int argc, VALUE *argv, VALUE self)
|
||||||
}
|
}
|
||||||
#endif
|
#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
|
void
|
||||||
Init_ossl_kdf(void)
|
Init_ossl_kdf(void)
|
||||||
{
|
{
|
||||||
|
@ -162,6 +256,7 @@ Init_ossl_kdf(void)
|
||||||
* * PKCS #5 PBKDF2 (Password-Based Key Derivation Function 2) in
|
* * PKCS #5 PBKDF2 (Password-Based Key Derivation Function 2) in
|
||||||
* combination with HMAC
|
* combination with HMAC
|
||||||
* * scrypt
|
* * scrypt
|
||||||
|
* * HKDF
|
||||||
*
|
*
|
||||||
* == Examples
|
* == Examples
|
||||||
* === Generating a 128 bit key for a Cipher (e.g. AES)
|
* === 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)
|
#if defined(HAVE_EVP_PBE_SCRYPT)
|
||||||
rb_define_module_function(mKDF, "scrypt", kdf_scrypt, -1);
|
rb_define_module_function(mKDF, "scrypt", kdf_scrypt, -1);
|
||||||
#endif
|
#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)
|
ossl_spki_set_public_key(VALUE self, VALUE key)
|
||||||
{
|
{
|
||||||
NETSCAPE_SPKI *spki;
|
NETSCAPE_SPKI *spki;
|
||||||
|
EVP_PKEY *pkey;
|
||||||
|
|
||||||
GetSPKI(self, spki);
|
GetSPKI(self, spki);
|
||||||
if (!NETSCAPE_SPKI_set_pubkey(spki, GetPKeyPtr(key))) { /* NO NEED TO DUP */
|
pkey = GetPKeyPtr(key);
|
||||||
ossl_raise(eSPKIError, NULL);
|
ossl_pkey_check_public_key(pkey);
|
||||||
}
|
if (!NETSCAPE_SPKI_set_pubkey(spki, pkey))
|
||||||
|
ossl_raise(eSPKIError, "NETSCAPE_SPKI_set_pubkey");
|
||||||
return key;
|
return key;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -307,17 +308,20 @@ static VALUE
|
||||||
ossl_spki_verify(VALUE self, VALUE key)
|
ossl_spki_verify(VALUE self, VALUE key)
|
||||||
{
|
{
|
||||||
NETSCAPE_SPKI *spki;
|
NETSCAPE_SPKI *spki;
|
||||||
|
EVP_PKEY *pkey;
|
||||||
|
|
||||||
GetSPKI(self, spki);
|
GetSPKI(self, spki);
|
||||||
switch (NETSCAPE_SPKI_verify(spki, GetPKeyPtr(key))) { /* NO NEED TO DUP */
|
pkey = GetPKeyPtr(key);
|
||||||
case 0:
|
ossl_pkey_check_public_key(pkey);
|
||||||
|
switch (NETSCAPE_SPKI_verify(spki, pkey)) {
|
||||||
|
case 0:
|
||||||
|
ossl_clear_error();
|
||||||
return Qfalse;
|
return Qfalse;
|
||||||
case 1:
|
case 1:
|
||||||
return Qtrue;
|
return Qtrue;
|
||||||
default:
|
default:
|
||||||
ossl_raise(eSPKIError, NULL);
|
ossl_raise(eSPKIError, "NETSCAPE_SPKI_verify");
|
||||||
}
|
}
|
||||||
return Qnil; /* dummy */
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Document-class: OpenSSL::Netscape::SPKI
|
/* 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);
|
return ossl_pkey_new(pkey);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
void
|
||||||
pkey_check_public_key(EVP_PKEY *pkey)
|
ossl_pkey_check_public_key(const EVP_PKEY *pkey)
|
||||||
{
|
{
|
||||||
void *ptr;
|
void *ptr;
|
||||||
const BIGNUM *n, *e, *pubkey;
|
const BIGNUM *n, *e, *pubkey;
|
||||||
|
@ -172,7 +172,8 @@ pkey_check_public_key(EVP_PKEY *pkey)
|
||||||
if (EVP_PKEY_missing_parameters(pkey))
|
if (EVP_PKEY_missing_parameters(pkey))
|
||||||
ossl_raise(ePKeyError, "parameters missing");
|
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)) {
|
switch (EVP_PKEY_base_id(pkey)) {
|
||||||
case EVP_PKEY_RSA:
|
case EVP_PKEY_RSA:
|
||||||
RSA_get0_key(ptr, &n, &e, NULL);
|
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;
|
int siglen, result;
|
||||||
|
|
||||||
GetPKey(self, pkey);
|
GetPKey(self, pkey);
|
||||||
pkey_check_public_key(pkey);
|
ossl_pkey_check_public_key(pkey);
|
||||||
md = ossl_evp_get_digestbyname(digest);
|
md = ossl_evp_get_digestbyname(digest);
|
||||||
StringValue(sig);
|
StringValue(sig);
|
||||||
siglen = RSTRING_LENINT(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);
|
void ossl_generate_cb_stop(void *ptr);
|
||||||
|
|
||||||
VALUE ossl_pkey_new(EVP_PKEY *);
|
VALUE ossl_pkey_new(EVP_PKEY *);
|
||||||
|
void ossl_pkey_check_public_key(const EVP_PKEY *);
|
||||||
EVP_PKEY *GetPKeyPtr(VALUE);
|
EVP_PKEY *GetPKeyPtr(VALUE);
|
||||||
EVP_PKEY *DupPKeyPtr(VALUE);
|
EVP_PKEY *DupPKeyPtr(VALUE);
|
||||||
EVP_PKEY *GetPrivPKeyPtr(VALUE);
|
EVP_PKEY *GetPrivPKeyPtr(VALUE);
|
||||||
|
|
|
@ -536,6 +536,196 @@ ossl_rsa_private_decrypt(int argc, VALUE *argv, VALUE self)
|
||||||
return str;
|
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:
|
* call-seq:
|
||||||
* rsa.params => hash
|
* 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, "public_decrypt", ossl_rsa_public_decrypt, -1);
|
||||||
rb_define_method(cRSA, "private_encrypt", ossl_rsa_private_encrypt, -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, "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, n);
|
||||||
DEF_OSSL_PKEY_BN(cRSA, rsa, e);
|
DEF_OSSL_PKEY_BN(cRSA, rsa, e);
|
||||||
|
|
|
@ -32,7 +32,7 @@ VALUE cSSLSocket;
|
||||||
static VALUE eSSLErrorWaitReadable;
|
static VALUE eSSLErrorWaitReadable;
|
||||||
static VALUE eSSLErrorWaitWritable;
|
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;
|
id_npn_protocols_encoded;
|
||||||
static VALUE sym_exception, sym_wait_readable, sym_wait_writable;
|
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))
|
if (NIL_P(cb))
|
||||||
return Qnil;
|
return Qnil;
|
||||||
|
|
||||||
ary = rb_funcall(cb, rb_intern("call"), 1, obj);
|
ary = rb_funcallv(cb, id_call, 1, &obj);
|
||||||
Check_Type(ary, T_ARRAY);
|
Check_Type(ary, T_ARRAY);
|
||||||
GetX509CertPtr(cert = rb_ary_entry(ary, 0));
|
GetX509CertPtr(cert = rb_ary_entry(ary, 0));
|
||||||
GetPrivPKeyPtr(key = rb_ary_entry(ary, 1));
|
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);
|
cb = rb_funcall(args->ssl_obj, args->id, 0);
|
||||||
if (NIL_P(cb))
|
if (NIL_P(cb))
|
||||||
return NULL;
|
return NULL;
|
||||||
dh = rb_funcall(cb, rb_intern("call"), 3,
|
dh = rb_funcall(cb, id_call, 3, args->ssl_obj, INT2NUM(args->is_export),
|
||||||
args->ssl_obj, INT2NUM(args->is_export), INT2NUM(args->keylength));
|
INT2NUM(args->keylength));
|
||||||
pkey = GetPKeyPtr(dh);
|
pkey = GetPKeyPtr(dh);
|
||||||
if (EVP_PKEY_base_id(pkey) != args->type)
|
if (EVP_PKEY_base_id(pkey) != args->type)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
@ -374,12 +374,12 @@ ossl_call_session_get_cb(VALUE ary)
|
||||||
cb = rb_funcall(ssl_obj, rb_intern("session_get_cb"), 0);
|
cb = rb_funcall(ssl_obj, rb_intern("session_get_cb"), 0);
|
||||||
if (NIL_P(cb)) return Qnil;
|
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) */
|
/* this method is currently only called for servers (in OpenSSL <= 0.9.8e) */
|
||||||
static SSL_SESSION *
|
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)
|
ossl_sslctx_session_get_cb(SSL *ssl, const unsigned char *buf, int len, int *copy)
|
||||||
#else
|
#else
|
||||||
ossl_sslctx_session_get_cb(SSL *ssl, unsigned char *buf, int len, int *copy)
|
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);
|
cb = rb_funcall(ssl_obj, rb_intern("session_new_cb"), 0);
|
||||||
if (NIL_P(cb)) return Qnil;
|
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 */
|
/* 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);
|
cb = rb_attr_get(sslctx_obj, id_i_session_remove_cb);
|
||||||
if (NIL_P(cb)) return Qnil;
|
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
|
static void
|
||||||
|
@ -533,7 +533,7 @@ ossl_call_servername_cb(VALUE ary)
|
||||||
cb = rb_attr_get(sslctx_obj, id_i_servername_cb);
|
cb = rb_attr_get(sslctx_obj, id_i_servername_cb);
|
||||||
if (NIL_P(cb)) return Qnil;
|
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)) {
|
if (rb_obj_is_kind_of(ret_obj, cSSLContext)) {
|
||||||
SSL *ssl;
|
SSL *ssl;
|
||||||
SSL_CTX *ctx2;
|
SSL_CTX *ctx2;
|
||||||
|
@ -585,7 +585,7 @@ ssl_renegotiation_cb(const SSL *ssl)
|
||||||
cb = rb_attr_get(sslctx_obj, id_i_renegotiation_cb);
|
cb = rb_attr_get(sslctx_obj, id_i_renegotiation_cb);
|
||||||
if (NIL_P(cb)) return;
|
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) || \
|
#if !defined(OPENSSL_NO_NEXTPROTONEG) || \
|
||||||
|
@ -635,7 +635,7 @@ npn_select_cb_common_i(VALUE tmp)
|
||||||
in += l;
|
in += l;
|
||||||
}
|
}
|
||||||
|
|
||||||
selected = rb_funcall(args->cb, rb_intern("call"), 1, protocols);
|
selected = rb_funcallv(args->cb, id_call, 1, &protocols);
|
||||||
StringValue(selected);
|
StringValue(selected);
|
||||||
len = RSTRING_LEN(selected);
|
len = RSTRING_LEN(selected);
|
||||||
if (len < 1 || len >= 256) {
|
if (len < 1 || len >= 256) {
|
||||||
|
@ -1193,6 +1193,134 @@ ossl_sslctx_set_security_level(VALUE self, VALUE value)
|
||||||
return 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:
|
* call-seq:
|
||||||
* ctx.session_add(session) -> true | false
|
* ctx.session_add(session) -> true | false
|
||||||
|
@ -2261,6 +2389,7 @@ Init_ossl_ssl(void)
|
||||||
rb_mWaitWritable = rb_define_module_under(rb_cIO, "WaitWritable");
|
rb_mWaitWritable = rb_define_module_under(rb_cIO, "WaitWritable");
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
id_call = rb_intern("call");
|
||||||
ID_callback_state = rb_intern("callback_state");
|
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);
|
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
|
* 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);
|
rb_attr(cSSLContext, rb_intern("cert"), 1, 1, Qfalse);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Context private key
|
* 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);
|
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
|
* An Array of extra X509 certificates to be added to the certificate
|
||||||
* chain.
|
* 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);
|
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, "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_get_security_level, 0);
|
||||||
rb_define_method(cSSLContext, "security_level=", ossl_sslctx_set_security_level, 1);
|
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_method(cSSLContext, "setup", ossl_sslctx_setup, 0);
|
||||||
rb_define_alias(cSSLContext, "freeze", "setup");
|
rb_define_alias(cSSLContext, "freeze", "setup");
|
||||||
|
|
|
@ -440,7 +440,7 @@ ossl_x509_set_not_before(VALUE self, VALUE time)
|
||||||
|
|
||||||
GetX509(self, x509);
|
GetX509(self, x509);
|
||||||
asn1time = ossl_x509_time_adjust(NULL, time);
|
asn1time = ossl_x509_time_adjust(NULL, time);
|
||||||
if (!X509_set_notBefore(x509, asn1time)) {
|
if (!X509_set1_notBefore(x509, asn1time)) {
|
||||||
ASN1_TIME_free(asn1time);
|
ASN1_TIME_free(asn1time);
|
||||||
ossl_raise(eX509CertError, "X509_set_notBefore");
|
ossl_raise(eX509CertError, "X509_set_notBefore");
|
||||||
}
|
}
|
||||||
|
@ -479,7 +479,7 @@ ossl_x509_set_not_after(VALUE self, VALUE time)
|
||||||
|
|
||||||
GetX509(self, x509);
|
GetX509(self, x509);
|
||||||
asn1time = ossl_x509_time_adjust(NULL, time);
|
asn1time = ossl_x509_time_adjust(NULL, time);
|
||||||
if (!X509_set_notAfter(x509, asn1time)) {
|
if (!X509_set1_notAfter(x509, asn1time)) {
|
||||||
ASN1_TIME_free(asn1time);
|
ASN1_TIME_free(asn1time);
|
||||||
ossl_raise(eX509CertError, "X509_set_notAfter");
|
ossl_raise(eX509CertError, "X509_set_notAfter");
|
||||||
}
|
}
|
||||||
|
@ -508,18 +508,19 @@ ossl_x509_get_public_key(VALUE self)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* call-seq:
|
* call-seq:
|
||||||
* cert.public_key = key => key
|
* cert.public_key = key
|
||||||
*/
|
*/
|
||||||
static VALUE
|
static VALUE
|
||||||
ossl_x509_set_public_key(VALUE self, VALUE key)
|
ossl_x509_set_public_key(VALUE self, VALUE key)
|
||||||
{
|
{
|
||||||
X509 *x509;
|
X509 *x509;
|
||||||
|
EVP_PKEY *pkey;
|
||||||
|
|
||||||
GetX509(self, x509);
|
GetX509(self, x509);
|
||||||
if (!X509_set_pubkey(x509, GetPKeyPtr(key))) { /* DUPs pkey */
|
pkey = GetPKeyPtr(key);
|
||||||
ossl_raise(eX509CertError, NULL);
|
ossl_pkey_check_public_key(pkey);
|
||||||
}
|
if (!X509_set_pubkey(x509, pkey))
|
||||||
|
ossl_raise(eX509CertError, "X509_set_pubkey");
|
||||||
return key;
|
return key;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -557,9 +558,9 @@ ossl_x509_verify(VALUE self, VALUE key)
|
||||||
X509 *x509;
|
X509 *x509;
|
||||||
EVP_PKEY *pkey;
|
EVP_PKEY *pkey;
|
||||||
|
|
||||||
pkey = GetPKeyPtr(key); /* NO NEED TO DUP */
|
|
||||||
GetX509(self, x509);
|
GetX509(self, x509);
|
||||||
|
pkey = GetPKeyPtr(key);
|
||||||
|
ossl_pkey_check_public_key(pkey);
|
||||||
switch (X509_verify(x509, pkey)) {
|
switch (X509_verify(x509, pkey)) {
|
||||||
case 1:
|
case 1:
|
||||||
return Qtrue;
|
return Qtrue;
|
||||||
|
@ -683,6 +684,26 @@ ossl_x509_inspect(VALUE self)
|
||||||
ossl_x509_get_not_after(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
|
* INIT
|
||||||
*/
|
*/
|
||||||
|
@ -821,4 +842,5 @@ Init_ossl_x509cert(void)
|
||||||
rb_define_method(cX509Cert, "extensions=", ossl_x509_set_extensions, 1);
|
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, "add_extension", ossl_x509_add_extension, 1);
|
||||||
rb_define_method(cX509Cert, "inspect", ossl_x509_inspect, 0);
|
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);
|
GetX509CRL(self, crl);
|
||||||
asn1time = ossl_x509_time_adjust(NULL, time);
|
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);
|
ASN1_TIME_free(asn1time);
|
||||||
ossl_raise(eX509CRLError, "X509_CRL_set_lastUpdate");
|
ossl_raise(eX509CRLError, "X509_CRL_set_lastUpdate");
|
||||||
}
|
}
|
||||||
|
@ -257,7 +257,7 @@ ossl_x509crl_set_next_update(VALUE self, VALUE time)
|
||||||
|
|
||||||
GetX509CRL(self, crl);
|
GetX509CRL(self, crl);
|
||||||
asn1time = ossl_x509_time_adjust(NULL, time);
|
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);
|
ASN1_TIME_free(asn1time);
|
||||||
ossl_raise(eX509CRLError, "X509_CRL_set_nextUpdate");
|
ossl_raise(eX509CRLError, "X509_CRL_set_nextUpdate");
|
||||||
}
|
}
|
||||||
|
@ -359,9 +359,12 @@ static VALUE
|
||||||
ossl_x509crl_verify(VALUE self, VALUE key)
|
ossl_x509crl_verify(VALUE self, VALUE key)
|
||||||
{
|
{
|
||||||
X509_CRL *crl;
|
X509_CRL *crl;
|
||||||
|
EVP_PKEY *pkey;
|
||||||
|
|
||||||
GetX509CRL(self, crl);
|
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:
|
case 1:
|
||||||
return Qtrue;
|
return Qtrue;
|
||||||
case 0:
|
case 0:
|
||||||
|
|
|
@ -293,11 +293,10 @@ ossl_x509req_set_public_key(VALUE self, VALUE key)
|
||||||
EVP_PKEY *pkey;
|
EVP_PKEY *pkey;
|
||||||
|
|
||||||
GetX509Req(self, req);
|
GetX509Req(self, req);
|
||||||
pkey = GetPKeyPtr(key); /* NO NEED TO DUP */
|
pkey = GetPKeyPtr(key);
|
||||||
if (!X509_REQ_set_pubkey(req, pkey)) {
|
ossl_pkey_check_public_key(pkey);
|
||||||
ossl_raise(eX509ReqError, NULL);
|
if (!X509_REQ_set_pubkey(req, pkey))
|
||||||
}
|
ossl_raise(eX509ReqError, "X509_REQ_set_pubkey");
|
||||||
|
|
||||||
return key;
|
return key;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -328,7 +327,8 @@ ossl_x509req_verify(VALUE self, VALUE key)
|
||||||
EVP_PKEY *pkey;
|
EVP_PKEY *pkey;
|
||||||
|
|
||||||
GetX509Req(self, req);
|
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)) {
|
switch (X509_REQ_verify(req, pkey)) {
|
||||||
case 1:
|
case 1:
|
||||||
return Qtrue;
|
return Qtrue;
|
||||||
|
|
|
@ -249,6 +249,26 @@ ossl_x509revoked_add_extension(VALUE self, VALUE ext)
|
||||||
return 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
|
* 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_get_extensions, 0);
|
||||||
rb_define_method(cX509Rev, "extensions=", ossl_x509revoked_set_extensions, 1);
|
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, "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
|
assert_equal tag1, tag2
|
||||||
end
|
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
|
private
|
||||||
|
|
||||||
def new_encryptor(algo, **kwargs)
|
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))
|
assert_equal(expected, OpenSSL::KDF.scrypt(pass, salt: salt, N: n, r: r, p: p, length: dklen))
|
||||||
end
|
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
|
private
|
||||||
|
|
||||||
def B(ary)
|
def B(ary)
|
||||||
|
|
|
@ -122,12 +122,12 @@ class OpenSSL::TestOCSP < OpenSSL::TestCase
|
||||||
|
|
||||||
assert_equal true, req.verify([@cert], store, OpenSSL::OCSP::NOINTERN)
|
assert_equal true, req.verify([@cert], store, OpenSSL::OCSP::NOINTERN)
|
||||||
ret = req.verify([@cert], store)
|
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
|
assert_equal true, ret
|
||||||
else
|
else
|
||||||
# RT2560; OCSP_request_verify() does not find signer cert from 'certs' when
|
# RT2560; OCSP_request_verify() does not find signer cert from 'certs' when
|
||||||
# OCSP_NOINTERN is not specified.
|
# 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"
|
pend "RT2560: ocsp_req_find_signer"
|
||||||
end
|
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_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)
|
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]
|
single1 = bres.responses[0]
|
||||||
assert_equal false, single1.check_validity
|
assert_equal false, single1.check_validity
|
||||||
assert_equal false, single1.check_validity(30)
|
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
|
||||||
assert_equal true, single2.check_validity(0, 500)
|
assert_equal true, single2.check_validity(0, 500)
|
||||||
assert_equal false, single2.check_validity(0, 200)
|
assert_equal false, single2.check_validity(0, 200)
|
||||||
|
single3 = bres.responses[2]
|
||||||
|
assert_equal false, single3.check_validity
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_response
|
def test_response
|
||||||
|
|
|
@ -362,6 +362,15 @@ module OpenSSL::TestPairM
|
||||||
}
|
}
|
||||||
end
|
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
|
def test_partial_tls_record_read_nonblock
|
||||||
ssl_pair { |s1, s2|
|
ssl_pair { |s1, s2|
|
||||||
# the beginning of a TLS record
|
# the beginning of a TLS record
|
||||||
|
|
|
@ -113,6 +113,39 @@ class OpenSSL::TestPKeyRSA < OpenSSL::PKeyTestCase
|
||||||
}
|
}
|
||||||
end
|
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
|
def test_RSAPrivateKey
|
||||||
rsa1024 = Fixtures.pkey("rsa1024")
|
rsa1024 = Fixtures.pkey("rsa1024")
|
||||||
asn1 = OpenSSL::ASN1::Sequence([
|
asn1 = OpenSSL::ASN1::Sequence([
|
||||||
|
|
|
@ -54,6 +54,87 @@ class OpenSSL::TestSSL < OpenSSL::SSLTestCase
|
||||||
}
|
}
|
||||||
end
|
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
|
def test_sysread_and_syswrite
|
||||||
start_server { |port|
|
start_server { |port|
|
||||||
server_connect(port) { |ssl|
|
server_connect(port) { |ssl|
|
||||||
|
@ -1222,6 +1303,59 @@ end
|
||||||
end
|
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
|
def test_dh_callback
|
||||||
pend "TLS 1.2 is not supported" unless tls12_supported?
|
pend "TLS 1.2 is not supported" unless tls12_supported?
|
||||||
|
|
||||||
|
@ -1336,11 +1470,24 @@ end
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
assert_equal(1, ctx.security_level)
|
assert_equal(1, ctx.security_level)
|
||||||
# assert_raise(OpenSSL::SSL::SSLError) { ctx.key = Fixtures.pkey("dsa512") }
|
|
||||||
# ctx.key = Fixtures.pkey("rsa1024")
|
dsa512 = Fixtures.pkey("dsa512")
|
||||||
# ctx.security_level = 2
|
dsa512_cert = issue_cert(@svr, dsa512, 50, [], @ca_cert, @ca_key)
|
||||||
# assert_raise(OpenSSL::SSL::SSLError) { ctx.key = Fixtures.pkey("rsa1024") }
|
rsa1024 = Fixtures.pkey("rsa1024")
|
||||||
pend "FIXME: SSLContext#key= currently does not raise because SSL_CTX_use_certificate() is delayed"
|
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
|
end
|
||||||
|
|
||||||
def test_dup
|
def test_dup
|
||||||
|
|
|
@ -62,6 +62,23 @@ class OpenSSL::TestX509Attribute < OpenSSL::TestCase
|
||||||
attr = OpenSSL::X509::Attribute.new("challengePassword", val)
|
attr = OpenSSL::X509::Attribute.new("challengePassword", val)
|
||||||
assert_equal(attr.to_der, attr.dup.to_der)
|
assert_equal(attr.to_der, attr.dup.to_der)
|
||||||
end
|
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
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
|
@ -169,6 +169,26 @@ class OpenSSL::TestX509Certificate < OpenSSL::TestCase
|
||||||
}
|
}
|
||||||
end
|
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
|
private
|
||||||
|
|
||||||
def certificate_error_returns_false
|
def certificate_error_returns_false
|
||||||
|
|
|
@ -197,6 +197,58 @@ class OpenSSL::TestX509CRL < OpenSSL::TestCase
|
||||||
assert_equal(false, crl.verify(@dsa512))
|
assert_equal(false, crl.verify(@dsa512))
|
||||||
end
|
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
|
private
|
||||||
|
|
||||||
def crl_error_returns_false
|
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(@basic_constraints.to_der, ext.to_der)
|
||||||
assert_equal(ext.to_der, ext.dup.to_der)
|
assert_equal(ext.to_der, ext.dup.to_der)
|
||||||
end
|
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
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
|
@ -141,6 +141,16 @@ class OpenSSL::TestX509Request < OpenSSL::TestCase
|
||||||
assert_equal(req.to_der, req.dup.to_der)
|
assert_equal(req.to_der, req.dup.to_der)
|
||||||
end
|
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
|
private
|
||||||
|
|
||||||
def request_error_returns_false
|
def request_error_returns_false
|
||||||
|
|
|
@ -67,7 +67,7 @@ module OpenSSL::TestUtils
|
||||||
cert.serial = serial
|
cert.serial = serial
|
||||||
cert.subject = dn
|
cert.subject = dn
|
||||||
cert.issuer = issuer.subject
|
cert.issuer = issuer.subject
|
||||||
cert.public_key = key.public_key
|
cert.public_key = key
|
||||||
now = Time.now
|
now = Time.now
|
||||||
cert.not_before = not_before || now - 3600
|
cert.not_before = not_before || now - 3600
|
||||||
cert.not_after = not_after || now + 3600
|
cert.not_after = not_after || now + 3600
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue