Skip to content

Commit

Permalink
Propagate precise encryption key length errors
Browse files Browse the repository at this point in the history
  • Loading branch information
zeroSteiner committed Feb 23, 2024
1 parent 9458743 commit 29025a0
Show file tree
Hide file tree
Showing 4 changed files with 31 additions and 10 deletions.
14 changes: 11 additions & 3 deletions lib/rex/proto/kerberos/crypto/aes_block_cipher_base.rb
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ class AesBlockCipherBase < BlockCipherBase
HASH_FUNCTION = 'SHA1'

# Subclasses must also define ENCRYPT_CIPHER_NAME and DECRYPT_CIPHER_NAME

# Derive an encryption key based on a password and salt for the given cipher type
#
# @param password [String] The password to use as the basis for key generation
Expand All @@ -30,11 +30,15 @@ def string_to_key(password, salt, params: nil)
tkey = random_to_key(seed)
derive(tkey, 'kerberos'.encode('utf-8'))
end

def encrypt_basic(plaintext, key)
raise Rex::Proto::Kerberos::Model::Error::KerberosError, 'Ciphertext too short' if plaintext.length < BLOCK_SIZE

cipher = OpenSSL::Cipher.new(self.class::ENCRYPT_CIPHER_NAME)
if key.length != cipher.key_len
raise Rex::Proto::Kerberos::Model::Error::KerberosError, "Encryption key length must be #{cipher.key_len} for #{self.class::ENCRYPT_CIPHER_NAME}"
end

cipher.encrypt
cipher.key = key
cipher.padding = 0
Expand All @@ -51,11 +55,15 @@ def encrypt_basic(plaintext, key)

ciphertext
end

def decrypt_basic(ciphertext, key)
raise Rex::Proto::Kerberos::Model::Error::KerberosError, 'Ciphertext too short' if ciphertext.length < BLOCK_SIZE

cipher = OpenSSL::Cipher.new(self.class::DECRYPT_CIPHER_NAME)
if key.length != cipher.key_len
raise Rex::Proto::Kerberos::Model::Error::KerberosError, "Decryption key length must be #{cipher.key_len} for #{self.class::ENCRYPT_CIPHER_NAME}"
end

cipher.decrypt
cipher.key = key
cipher.padding = 0
Expand Down
17 changes: 12 additions & 5 deletions lib/rex/proto/kerberos/crypto/des3_cbc_sha1.rb
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,11 @@ def decrypt_asn1(ciphertext, key, msg_type)
# Decrypts the cipher using DES3-CBC-SHA1 schema
def decrypt_basic(ciphertext, key)
raise Rex::Proto::Kerberos::Model::Error::KerberosError, 'Ciphertext is not a multiple of block length' unless ciphertext.length % BLOCK_SIZE == 0

cipher = OpenSSL::Cipher.new('des-ede3-cbc')
if key.length != cipher.key_len
raise Rex::Proto::Kerberos::Model::Error::KerberosError, "Decryption key length must be #{cipher.key_len} for des-ede3-cbc"
end
cipher.decrypt
cipher.key = key
cipher.padding = 0
Expand All @@ -51,6 +55,9 @@ def decrypt_basic(ciphertext, key)
# Encrypts the cipher using DES3-CBC-SHA1 schema
def encrypt_basic(plaintext, key)
cipher = OpenSSL::Cipher.new('des-ede3-cbc')
if key.length != cipher.key_len
raise Rex::Proto::Kerberos::Model::Error::KerberosError, "Encryption key length must be #{cipher.key_len} for des-ede3-cbc"
end
cipher.encrypt
cipher.key = key
cipher.padding = 0
Expand All @@ -66,22 +73,22 @@ def parity(b)
b &= ~1
b | (b.digits(2).count(1) + 1) % 2
end

raise Rex::Proto::Kerberos::Model::Error::KerberosError unless seed.length == 7

firstbytes = seed.map {|b| parity(b & ~1)}
tmp = 7.times.map { |i| (seed[i] & 1) << i+1 }
lastbyte = parity(tmp.sum)
keybytes = firstbytes + [lastbyte]
if _is_weak_des_key(keybytes)
keybytes[7] = keybytes[7] ^ 0xF0
end

keybytes
end

raise Rex::Proto::Kerberos::Model::Error::KerberosError unless seed.length == 21

subkeys = seed.each_slice(7).map { |slice| expand(slice) }
subkeys.flatten
end
Expand Down
6 changes: 6 additions & 0 deletions lib/rex/proto/kerberos/crypto/des_cbc_md5.rb
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,9 @@ def decrypt(ciphertext, key, msg_type)


cipher = OpenSSL::Cipher.new('des-cbc')
if key.length != cipher.key_len
raise Rex::Proto::Kerberos::Model::Error::KerberosError, "Decryption key length must be #{cipher.key_len} for des-cbc"
end
cipher.decrypt
cipher.padding = 0
cipher.key = key
Expand Down Expand Up @@ -137,6 +140,9 @@ def encrypt(plaintext, key, msg_type, confounder: nil)
plaintext = confounder + checksum + padded_data

cipher = OpenSSL::Cipher.new('des-cbc')
if key.length != cipher.key_len
raise Rex::Proto::Kerberos::Model::Error::KerberosError, "Encryption key length must be #{cipher.key_len} for des-cbc"
end
cipher.encrypt
cipher.padding = 0
cipher.key = key
Expand Down
4 changes: 2 additions & 2 deletions lib/rex/proto/kerberos/crypto/rc4_hmac.rb
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ def string_to_key(password, salt=nil, params: nil)
unicode_password = password.encode('utf-16le')
password_digest = OpenSSL::Digest.digest('MD4', unicode_password)
end

# Use this class's encryption routines to create a checksum of the data based on the key and message type
#
# @param key [String] the key to use to generate the checksum
Expand Down Expand Up @@ -261,7 +261,7 @@ def calculate_encrypted_length(plaintext_len)

def usage_str(msg_type)
usage_table = {
Rex::Proto::Kerberos::Crypto::KeyUsage::AS_REP_ENCPART => Rex::Proto::Kerberos::Crypto::KeyUsage::TGS_REP_ENCPART_SESSION_KEY,
Rex::Proto::Kerberos::Crypto::KeyUsage::AS_REP_ENCPART => Rex::Proto::Kerberos::Crypto::KeyUsage::TGS_REP_ENCPART_SESSION_KEY,
Rex::Proto::Kerberos::Crypto::KeyUsage::GSS_ACCEPTOR_SIGN => Rex::Proto::Kerberos::Crypto::KeyUsage::KRB_PRIV_ENCPART
}
usage_mapped = usage_table.fetch(msg_type) { msg_type }
Expand Down

0 comments on commit 29025a0

Please sign in to comment.