mirror of
https://github.com/ruby/ruby.git
synced 2022-11-09 12:17:21 -05:00
[ruby/openssl] Define Cipher #ccm_data_len= for CCM mode ciphers
Allow specifying just length to #update CCM mode ciphers need to specify the total plaintext or ciphertext length to EVP_CipherUpdate. Update the link to the tests file Define Cipher#ccm_data_len= for CCM mode ciphers Add a unit test for CCM mode Also check CCM is authenticated when testing https://github.com/ruby/openssl/commit/bb3816953b
This commit is contained in:
parent
fad3412d47
commit
4d8bce227c
Notes:
git
2021-03-16 20:38:57 +09:00
2 changed files with 68 additions and 0 deletions
|
@ -813,6 +813,31 @@ ossl_cipher_block_size(VALUE self)
|
||||||
return INT2NUM(EVP_CIPHER_CTX_block_size(ctx));
|
return INT2NUM(EVP_CIPHER_CTX_block_size(ctx));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* call-seq:
|
||||||
|
* cipher.ccm_data_len = integer -> integer
|
||||||
|
*
|
||||||
|
* Sets the length of the plaintext / ciphertext message that will be
|
||||||
|
* processed in CCM mode. Make sure to call this method after #key= and
|
||||||
|
* #iv= have been set, and before #auth_data=.
|
||||||
|
*
|
||||||
|
* Only call this method after calling Cipher#encrypt or Cipher#decrypt.
|
||||||
|
*/
|
||||||
|
static VALUE
|
||||||
|
ossl_cipher_set_ccm_data_len(VALUE self, VALUE data_len)
|
||||||
|
{
|
||||||
|
int in_len, out_len;
|
||||||
|
EVP_CIPHER_CTX *ctx;
|
||||||
|
|
||||||
|
in_len = NUM2INT(data_len);
|
||||||
|
|
||||||
|
GetCipher(self, ctx);
|
||||||
|
if (EVP_CipherUpdate(ctx, NULL, &out_len, NULL, in_len) != 1)
|
||||||
|
ossl_raise(eCipherError, NULL);
|
||||||
|
|
||||||
|
return data_len;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* INIT
|
* INIT
|
||||||
*/
|
*/
|
||||||
|
@ -1043,6 +1068,7 @@ Init_ossl_cipher(void)
|
||||||
rb_define_method(cCipher, "iv_len", ossl_cipher_iv_length, 0);
|
rb_define_method(cCipher, "iv_len", ossl_cipher_iv_length, 0);
|
||||||
rb_define_method(cCipher, "block_size", ossl_cipher_block_size, 0);
|
rb_define_method(cCipher, "block_size", ossl_cipher_block_size, 0);
|
||||||
rb_define_method(cCipher, "padding=", ossl_cipher_set_padding, 1);
|
rb_define_method(cCipher, "padding=", ossl_cipher_set_padding, 1);
|
||||||
|
rb_define_method(cCipher, "ccm_data_len=", ossl_cipher_set_ccm_data_len, 1);
|
||||||
|
|
||||||
id_auth_tag_len = rb_intern_const("auth_tag_len");
|
id_auth_tag_len = rb_intern_const("auth_tag_len");
|
||||||
id_key_set = rb_intern_const("key_set");
|
id_key_set = rb_intern_const("key_set");
|
||||||
|
|
|
@ -174,6 +174,48 @@ class OpenSSL::TestCipher < OpenSSL::TestCase
|
||||||
assert_not_predicate(cipher, :authenticated?)
|
assert_not_predicate(cipher, :authenticated?)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def test_aes_ccm
|
||||||
|
# RFC 3610 Section 8, Test Case 1
|
||||||
|
key = ["c0c1c2c3c4c5c6c7c8c9cacbcccdcecf"].pack("H*")
|
||||||
|
iv = ["00000003020100a0a1a2a3a4a5"].pack("H*")
|
||||||
|
aad = ["0001020304050607"].pack("H*")
|
||||||
|
pt = ["08090a0b0c0d0e0f101112131415161718191a1b1c1d1e"].pack("H*")
|
||||||
|
ct = ["588c979a61c663d2f066d0c2c0f989806d5f6b61dac384"].pack("H*")
|
||||||
|
tag = ["17e8d12cfdf926e0"].pack("H*")
|
||||||
|
|
||||||
|
kwargs = {auth_tag_len: 8, iv_len: 13, key: key, iv: iv}
|
||||||
|
cipher = new_encryptor("aes-128-ccm", **kwargs, ccm_data_len: pt.length, auth_data: aad)
|
||||||
|
assert_equal ct, cipher.update(pt) << cipher.final
|
||||||
|
assert_equal tag, cipher.auth_tag
|
||||||
|
cipher = new_decryptor("aes-128-ccm", **kwargs, ccm_data_len: ct.length, auth_tag: tag, auth_data: aad)
|
||||||
|
assert_equal pt, cipher.update(ct) << cipher.final
|
||||||
|
|
||||||
|
# truncated tag is accepted
|
||||||
|
cipher = new_encryptor("aes-128-ccm", **kwargs, ccm_data_len: pt.length, auth_data: aad)
|
||||||
|
assert_equal ct, cipher.update(pt) << cipher.final
|
||||||
|
assert_equal tag[0, 8], cipher.auth_tag(8)
|
||||||
|
cipher = new_decryptor("aes-128-ccm", **kwargs, ccm_data_len: ct.length, auth_tag: tag[0, 8], auth_data: aad)
|
||||||
|
assert_equal pt, cipher.update(ct) << cipher.final
|
||||||
|
|
||||||
|
# wrong tag is rejected
|
||||||
|
tag2 = tag.dup
|
||||||
|
tag2.setbyte(-1, (tag2.getbyte(-1) + 1) & 0xff)
|
||||||
|
cipher = new_decryptor("aes-128-ccm", **kwargs, ccm_data_len: ct.length, auth_tag: tag2, auth_data: aad)
|
||||||
|
assert_raise(OpenSSL::Cipher::CipherError) { cipher.update(ct) }
|
||||||
|
|
||||||
|
# wrong aad is rejected
|
||||||
|
aad2 = aad[0..-2] << aad[-1].succ
|
||||||
|
cipher = new_decryptor("aes-128-ccm", **kwargs, ccm_data_len: ct.length, auth_tag: tag, auth_data: aad2)
|
||||||
|
assert_raise(OpenSSL::Cipher::CipherError) { cipher.update(ct) }
|
||||||
|
|
||||||
|
# wrong ciphertext is rejected
|
||||||
|
ct2 = ct[0..-2] << ct[-1].succ
|
||||||
|
cipher = new_decryptor("aes-128-ccm", **kwargs, ccm_data_len: ct2.length, auth_tag: tag, auth_data: aad)
|
||||||
|
assert_raise(OpenSSL::Cipher::CipherError) { cipher.update(ct2) }
|
||||||
|
end if has_cipher?("aes-128-ccm") &&
|
||||||
|
OpenSSL::Cipher.new("aes-128-ccm").authenticated? &&
|
||||||
|
OpenSSL::OPENSSL_VERSION_NUMBER >= 0x10101000 # version >= v1.1.1
|
||||||
|
|
||||||
def test_aes_gcm
|
def test_aes_gcm
|
||||||
# GCM spec Appendix B Test Case 4
|
# GCM spec Appendix B Test Case 4
|
||||||
key = ["feffe9928665731c6d6a8f9467308308"].pack("H*")
|
key = ["feffe9928665731c6d6a8f9467308308"].pack("H*")
|
||||||
|
|
Loading…
Add table
Reference in a new issue