Module: Rex::Proto::Kerberos::Crypto::GssNewEncryptionType
- Included in:
- AesBlockCipherBase
- Defined in:
- lib/rex/proto/kerberos/crypto/gss_new_encryption_type.rb
Overview
The RFC4121 implementation of GSS wrapping (Section 4.2.6.2) which applies to “newer encryption types” (defined as those not in section 1 of RFC4121) This mixin may be included by Encryption providers in Rex::Proto::Kerberos::Crypto
Constant Summary collapse
- GSS_SENT_BY_ACCEPTOR =
1
- GSS_SEALED =
2
- GSS_ACCEPTOR_SUBKEY =
4
- GSS_HEADER_LEN =
The length of the GSS header
16
- TOK_ID_GSS_WRAP =
0x0504
Instance Method Summary collapse
- #calculate_encrypted_length(plaintext_len) ⇒ Object
- #gss_unwrap(ciphertext, key, expected_sequence_number, is_initiator, opts = {}) ⇒ Object
-
#gss_wrap(plaintext, key, sequence_number, is_initiator, opts = {}) ⇒ String, Integer
Encrypt the message, wrapping it in GSS structures.
Instance Method Details
#calculate_encrypted_length(plaintext_len) ⇒ Object
91 92 93 |
# File 'lib/rex/proto/kerberos/crypto/gss_new_encryption_type.rb', line 91 def calculate_encrypted_length(plaintext_len) plaintext_len end |
#gss_unwrap(ciphertext, key, expected_sequence_number, is_initiator, opts = {}) ⇒ Object
59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 |
# File 'lib/rex/proto/kerberos/crypto/gss_new_encryption_type.rb', line 59 def gss_unwrap(ciphertext, key, expected_sequence_number, is_initiator, opts={}) use_acceptor_subkey = opts.fetch(:use_acceptor_subkey) { true } # Handle wrap-around sequence_number &= 0xFFFFFFFFFFFFFFFF expected_flags = GSS_SEALED expected_flags |= GSS_ACCEPTOR_SUBKEY if use_acceptor_subkey if is_initiator key_usage = Rex::Proto::Kerberos::Crypto::KeyUsage::GSS_ACCEPTOR_SEAL expected_flags |= GSS_SENT_BY_ACCEPTOR else key_usage = Rex::Proto::Kerberos::Crypto::KeyUsage::GSS_INITIATOR_SEAL end header = ciphertext[0,GSS_HEADER_LEN] ciphertext = ciphertext[GSS_HEADER_LEN, ciphertext.length] tok_id, flags, filler, ec, rrc, snd_seq = header.unpack('nCCnnQ>') raise Rex::Proto::Kerberos::Model::Error::KerberosError, 'Invalid token ID' unless tok_id == TOK_ID_GSS_WRAP raise Rex::Proto::Kerberos::Model::Error::KerberosError, 'Invalid filler' unless filler == 0xFF raise Rex::Proto::Kerberos::Model::Error::KerberosError, 'Unexpected flags' unless flags == expected_flags raise Rex::Proto::Kerberos::Model::Error::KerberosError, "Invalid sequence number (received #{snd_seq}; expected #{expected_sequence_number})" unless expected_sequence_number == snd_seq # Could do some sanity checking here of those values ciphertext = rotate(ciphertext, -(rrc+ec)) plaintext = self.decrypt(ciphertext, key.value, key_usage) plaintext = plaintext[0, plaintext.length - ec - GSS_HEADER_LEN] plaintext end |
#gss_wrap(plaintext, key, sequence_number, is_initiator, opts = {}) ⇒ String, Integer
Encrypt the message, wrapping it in GSS structures
24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 |
# File 'lib/rex/proto/kerberos/crypto/gss_new_encryption_type.rb', line 24 def gss_wrap(plaintext, key, sequence_number, is_initiator, opts={}) use_acceptor_subkey = opts.fetch(:use_acceptor_subkey) { true } # Handle wrap-around sequence_number &= 0xFFFFFFFFFFFFFFFF flags = GSS_SEALED flags |= GSS_ACCEPTOR_SUBKEY if use_acceptor_subkey if is_initiator key_usage = Rex::Proto::Kerberos::Crypto::KeyUsage::GSS_INITIATOR_SEAL else key_usage = Rex::Proto::Kerberos::Crypto::KeyUsage::GSS_ACCEPTOR_SEAL flags |= GSS_SENT_BY_ACCEPTOR end tok_id = TOK_ID_GSS_WRAP filler = 0xFF ec = calculate_ec(plaintext.length) rrc = calculate_rrc # RFC4121, Section 4.2.4 plaintext_header = [tok_id, flags, filler, 0, 0, sequence_number].pack('nCCnnQ>') header = [tok_id, flags, filler, ec, rrc, sequence_number].pack('nCCnnQ>') # "x" chosen as the filler based on the Linux implementation of the kerberos client # https://salsa.debian.org/debian/krb5/-/blob/0269810b1aec6c554fb746433f045d59fd34ab3a/src/lib/gssapi/krb5/k5sealv3.c#L160 ec_filler = "x" * ec plaintext = plaintext + ec_filler + plaintext_header ciphertext = self.encrypt(plaintext, key.value, key_usage) rotated = rotate(ciphertext, rrc+ec) result = [header + rotated, header_length + ec, ec] end |