1
0
Fork 0
mirror of https://github.com/ruby/ruby.git synced 2022-11-09 12:17:21 -05:00
ruby--ruby/test/openssl/test_cipher.rb
rhe c8cb26252a openssl: clear OpenSSL error queue before return to Ruby
* ext/openssl/ossl_x509cert.c (ossl_x509_verify): X509_verify()
  family may put errors on 0 return (0 means verification failure).
  Clear OpenSSL error queue before return to Ruby. Since the queue is
  thread global, remaining errors in the queue can cause an unexpected
  error in the next OpenSSL operation.  [ruby-core:48284] [Bug #7215]

* ext/openssl/ossl_x509crl.c (ossl_x509crl_verify): ditto.

* ext/openssl/ossl_x509req.c (ossl_x509req_verify): ditto.

* ext/openssl/ossl_x509store.c (ossl_x509stctx_verify): ditto.

* ext/openssl/ossl_pkey_dh.c (dh_generate): clear the OpenSSL error
  queue before re-raising exception.

* ext/openssl/ossl_pkey_dsa.c (dsa_generate): ditto.

* ext/openssl/ossl_pkey_rsa.c (rsa_generate): ditto.

* ext/openssl/ossl_ssl.c (ossl_start_ssl): ditto.

* test/openssl: check that OpenSSL.errors is empty every time after
  running a test case.

git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@55051 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2016-05-18 04:07:47 +00:00

262 lines
7 KiB
Ruby

# frozen_string_literal: false
require_relative 'utils'
if defined?(OpenSSL::TestUtils)
class OpenSSL::TestCipher < OpenSSL::TestCase
class << self
def has_cipher?(name)
ciphers = OpenSSL::Cipher.ciphers
# redefine method so we can use the cached ciphers value from the closure
# and need not recompute the list each time
define_singleton_method :has_cipher? do |name|
ciphers.include?(name)
end
has_cipher?(name)
end
def has_ciphers?(list)
list.all? { |name| has_cipher?(name) }
end
end
def setup
@c1 = OpenSSL::Cipher::Cipher.new("DES-EDE3-CBC")
@c2 = OpenSSL::Cipher::DES.new(:EDE3, "CBC")
@key = "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
@iv = "\0\0\0\0\0\0\0\0"
@hexkey = "0000000000000000000000000000000000000000000000"
@hexiv = "0000000000000000"
@data = "DATA"
end
def teardown
super
@c1 = @c2 = nil
end
def test_crypt
@c1.encrypt.pkcs5_keyivgen(@key, @iv)
@c2.encrypt.pkcs5_keyivgen(@key, @iv)
s1 = @c1.update(@data) + @c1.final
s2 = @c2.update(@data) + @c2.final
assert_equal(s1, s2, "encrypt")
@c1.decrypt.pkcs5_keyivgen(@key, @iv)
@c2.decrypt.pkcs5_keyivgen(@key, @iv)
assert_equal(@data, @c1.update(s1)+@c1.final, "decrypt")
assert_equal(@data, @c2.update(s2)+@c2.final, "decrypt")
end
def test_info
assert_equal("DES-EDE3-CBC", @c1.name, "name")
assert_equal("DES-EDE3-CBC", @c2.name, "name")
assert_kind_of(Integer, @c1.key_len, "key_len")
assert_kind_of(Integer, @c1.iv_len, "iv_len")
end
def test_dup
assert_equal(@c1.name, @c1.dup.name, "dup")
assert_equal(@c1.name, @c1.clone.name, "clone")
@c1.encrypt
@c1.key = @key
@c1.iv = @iv
tmpc = @c1.dup
s1 = @c1.update(@data) + @c1.final
s2 = tmpc.update(@data) + tmpc.final
assert_equal(s1, s2, "encrypt dup")
end
def test_reset
@c1.encrypt
@c1.key = @key
@c1.iv = @iv
s1 = @c1.update(@data) + @c1.final
@c1.reset
s2 = @c1.update(@data) + @c1.final
assert_equal(s1, s2, "encrypt reset")
end
def test_empty_data
@c1.encrypt
assert_raise(ArgumentError){ @c1.update("") }
end
def test_initialize
assert_raise(RuntimeError) {@c1.__send__(:initialize, "DES-EDE3-CBC")}
assert_raise(RuntimeError) {OpenSSL::Cipher.allocate.final}
end
def test_ctr_if_exists
begin
cipher = OpenSSL::Cipher.new('aes-128-ctr')
cipher.encrypt
cipher.pkcs5_keyivgen('password')
c = cipher.update('hello,world') + cipher.final
cipher.decrypt
cipher.pkcs5_keyivgen('password')
assert_equal('hello,world', cipher.update(c) + cipher.final)
end
end if has_cipher?('aes-128-ctr')
if OpenSSL::OPENSSL_VERSION_NUMBER > 0x00907000
def test_ciphers
OpenSSL::Cipher.ciphers.each{|name|
next if /netbsd/ =~ RUBY_PLATFORM && /idea|rc5/i =~ name
begin
assert_kind_of(OpenSSL::Cipher::Cipher, OpenSSL::Cipher::Cipher.new(name))
rescue OpenSSL::Cipher::CipherError => e
next if /wrap/ =~ name and e.message == 'wrap mode not allowed'
raise
end
}
end
def test_AES
pt = File.read(__FILE__)
%w(ECB CBC CFB OFB).each{|mode|
c1 = OpenSSL::Cipher::AES256.new(mode)
c1.encrypt
c1.pkcs5_keyivgen("passwd")
ct = c1.update(pt) + c1.final
c2 = OpenSSL::Cipher::AES256.new(mode)
c2.decrypt
c2.pkcs5_keyivgen("passwd")
assert_equal(pt, c2.update(ct) + c2.final)
}
end
def test_AES_crush
500.times do
assert_nothing_raised("[Bug #2768]") do
# it caused OpenSSL SEGV by uninitialized key
OpenSSL::Cipher::AES128.new("ECB").update "." * 17
end
end
end
end
if has_ciphers?(['aes-128-gcm', 'aes-192-gcm', 'aes-256-gcm'])
def test_authenticated
cipher = OpenSSL::Cipher.new('aes-128-gcm')
assert_predicate(cipher, :authenticated?)
cipher = OpenSSL::Cipher.new('aes-128-cbc')
assert_not_predicate(cipher, :authenticated?)
end
def test_aes_gcm
['aes-128-gcm', 'aes-192-gcm', 'aes-256-gcm'].each do |algo|
pt = "You should all use Authenticated Encryption!"
cipher, key, iv = new_encryptor(algo)
cipher.auth_data = "aad"
ct = cipher.update(pt) + cipher.final
tag = cipher.auth_tag
assert_equal(16, tag.size)
decipher = new_decryptor(algo, key, iv)
decipher.auth_tag = tag
decipher.auth_data = "aad"
assert_equal(pt, decipher.update(ct) + decipher.final)
end
end
def test_aes_gcm_short_tag
['aes-128-gcm', 'aes-192-gcm', 'aes-256-gcm'].each do |algo|
pt = "You should all use Authenticated Encryption!"
cipher, key, iv = new_encryptor(algo)
cipher.auth_data = "aad"
ct = cipher.update(pt) + cipher.final
tag = cipher.auth_tag(8)
assert_equal(8, tag.size)
decipher = new_decryptor(algo, key, iv)
decipher.auth_tag = tag
decipher.auth_data = "aad"
assert_equal(pt, decipher.update(ct) + decipher.final)
end
end
def test_aes_gcm_wrong_tag
pt = "You should all use Authenticated Encryption!"
cipher, key, iv = new_encryptor('aes-128-gcm')
cipher.auth_data = "aad"
ct = cipher.update(pt) + cipher.final
tag = cipher.auth_tag
decipher = new_decryptor('aes-128-gcm', key, iv)
tag.setbyte(-1, (tag.getbyte(-1) + 1) & 0xff)
decipher.auth_tag = tag
decipher.auth_data = "aad"
assert_raise OpenSSL::Cipher::CipherError do
decipher.update(ct) + decipher.final
end
end
def test_aes_gcm_wrong_auth_data
pt = "You should all use Authenticated Encryption!"
cipher, key, iv = new_encryptor('aes-128-gcm')
cipher.auth_data = "aad"
ct = cipher.update(pt) + cipher.final
tag = cipher.auth_tag
decipher = new_decryptor('aes-128-gcm', key, iv)
decipher.auth_tag = tag
decipher.auth_data = "daa"
assert_raise OpenSSL::Cipher::CipherError do
decipher.update(ct) + decipher.final
end
end
def test_aes_gcm_wrong_ciphertext
pt = "You should all use Authenticated Encryption!"
cipher, key, iv = new_encryptor('aes-128-gcm')
cipher.auth_data = "aad"
ct = cipher.update(pt) + cipher.final
tag = cipher.auth_tag
decipher = new_decryptor('aes-128-gcm', key, iv)
decipher.auth_tag = tag
decipher.auth_data = "aad"
assert_raise OpenSSL::Cipher::CipherError do
decipher.update(ct[0..-2] << ct[-1].succ) + decipher.final
end
end
end
private
def new_encryptor(algo)
cipher = OpenSSL::Cipher.new(algo)
cipher.encrypt
key = cipher.random_key
iv = cipher.random_iv
[cipher, key, iv]
end
def new_decryptor(algo, key, iv)
OpenSSL::Cipher.new(algo).tap do |cipher|
cipher.decrypt
cipher.key = key
cipher.iv = iv
end
end
end
end