Beispiel #1
0
        private bool DecryptRC4WithKey(KerberosKey key, RC4KeyUsage key_usage, out byte[] decrypted)
        {
            HMACMD5 hmac = new HMACMD5(key.Key);

            byte[] key1 = hmac.ComputeHash(BitConverter.GetBytes((int)key_usage));
            hmac = new HMACMD5(key1);

            byte[] checksum = new byte[16];
            Buffer.BlockCopy(CipherText, 0, checksum, 0, checksum.Length);
            byte[] key2 = hmac.ComputeHash(checksum);

            byte[] result = ARC4.Transform(CipherText, 16, CipherText.Length - 16, key2);
            hmac = new HMACMD5(key1);
            byte[] calculated_checksum = hmac.ComputeHash(result);

            decrypted = new byte[result.Length - 8];
            Buffer.BlockCopy(result, 8, decrypted, 0, decrypted.Length);
            return(NtObjectUtils.EqualByteArray(checksum, calculated_checksum));
        }
        private static byte[] SerializeEntry(KerberosKey entry)
        {
            MemoryStream stm    = new MemoryStream();
            BinaryWriter writer = new BinaryWriter(stm);

            WriteUInt16(writer, (ushort)entry.Components.Count());
            WriteString(writer, entry.Realm);
            foreach (string s in entry.Components)
            {
                WriteString(writer, s);
            }
            WriteInt32(writer, (int)entry.NameType);
            WriteUInt32(writer, (uint)entry.Timestamp.Subtract(new DateTime(1970, 1, 1)).TotalSeconds);
            writer.Write((byte)entry.Version);
            WriteUInt16(writer, (ushort)entry.KeyEncryption);
            WriteOctets(writer, entry.Key);
            WriteUInt32(writer, entry.Version);
            return(stm.ToArray());
        }
Beispiel #3
0
        private bool DecryptRC4(KerberosKeySet keyset, string realm, KerberosPrincipalName server_name, RC4KeyUsage key_usage, out byte[] decrypted)
        {
            KerberosKey key = keyset.FindKey(EncryptionType, server_name.NameType, server_name.GetPrincipal(realm), KeyVersion ?? 0);

            if (key != null)
            {
                if (DecryptRC4WithKey(key, key_usage, out decrypted))
                {
                    return(true);
                }
            }
            foreach (var next in keyset.GetKeysForEncryption(EncryptionType))
            {
                if (DecryptRC4WithKey(key, key_usage, out decrypted))
                {
                    return(true);
                }
            }
            decrypted = null;
            return(false);
        }
Beispiel #4
0
 /// <summary>
 /// Remove a key from the key set.
 /// </summary>
 /// <param name="key">The key to remove.</param>
 /// <returns>True if the key was removed.</returns>
 public bool Remove(KerberosKey key)
 {
     return(_keys.Remove(key));
 }
Beispiel #5
0
 /// <summary>
 /// Add a key to the key set.
 /// </summary>
 /// <param name="key">The key to add.</param>
 /// <returns>True if the key was added, false if the key already existed.</returns>
 public bool Add(KerberosKey key)
 {
     return(_keys.Add(key));
 }
Beispiel #6
0
 /// <summary>
 /// Constructor.
 /// </summary>
 /// <param name="key">The single kerberos key.</param>
 public KerberosKeySet(KerberosKey key) : this(new KerberosKey[] { key })
 {
 }
Beispiel #7
0
        internal static bool Parse(KerberosTicket orig_ticket, KerberosEncryptedData orig_data, byte[] decrypted, out KerberosEncryptedData ticket)
        {
            ticket = null;
            try
            {
                DERValue[] values = DERParser.ParseData(decrypted, 0);
                if (values.Length != 1)
                {
                    return(false);
                }
                DERValue value = values[0];
                if (!value.CheckApplication(2) || !value.HasChildren())
                {
                    return(false);
                }
                if (!value.Children[0].CheckSequence())
                {
                    return(false);
                }
                var ret = new KerberosAuthenticator(orig_data);
                foreach (var next in value.Children[0].Children)
                {
                    if (next.Type != DERTagType.ContextSpecific)
                    {
                        return(false);
                    }
                    switch (next.Tag)
                    {
                    case 0:
                        if (next.ReadChildInteger() != 5)
                        {
                            return(false);
                        }
                        break;

                    case 1:
                        ret.ClientRealm = next.ReadChildGeneralString();
                        break;

                    case 2:
                        if (!next.Children[0].CheckSequence())
                        {
                            return(false);
                        }
                        ret.ClientName = KerberosPrincipalName.Parse(next.Children[0]);
                        break;

                    case 3:
                        if (!next.Children[0].CheckSequence())
                        {
                            return(false);
                        }
                        ret.Checksum = Kerberos.KerberosChecksum.Parse(next.Children[0]);
                        break;

                    case 4:
                        ret.ClientUSec = next.ReadChildInteger();
                        break;

                    case 5:
                        ret.ClientTime = next.ReadChildGeneralizedTime();
                        break;

                    case 6:
                        if (!next.HasChildren())
                        {
                            return(false);
                        }
                        ret.SubKey = KerberosKey.Parse(next.Children[0], orig_ticket.Realm, orig_ticket.ServerName);
                        break;

                    case 7:
                        ret.SequenceNumber = next.ReadChildInteger();
                        break;

                    case 8:
                        if (!next.HasChildren())
                        {
                            return(false);
                        }
                        ret.AuthorizationData = KerberosAuthorizationData.ParseSequence(next.Children[0]);
                        break;

                    default:
                        return(false);
                    }
                }
                ticket = ret;
            }
            catch (InvalidDataException)
            {
                return(false);
            }
            catch (EndOfStreamException)
            {
                return(false);
            }
            return(true);
        }
Beispiel #8
0
        private bool DecryptAESWithKey(KerberosKey key, KeyUsage key_usage, out byte[] decrypted)
        {
            byte[] derive_enc_key;
            byte[] derive_mac_key;

            switch (key_usage)
            {
            case KeyUsage.AsRepTgsRepTicket:
                derive_enc_key = _aes_encrypt_ticket;
                derive_mac_key = _aes_verify_ticket;
                break;

            case KeyUsage.ApReqAuthSubKey:
                derive_enc_key = _aes_encrypt_auth;
                derive_mac_key = _aes_verify_auth;
                break;

            case KeyUsage.ApRepEncryptedPart:
                derive_enc_key = _aes_encrypt_ap_rep;
                derive_mac_key = _aes_verify_ap_rep;
                break;

            case KeyUsage.KrbCred:
                derive_enc_key = _aes_encrypt_krb_cred;
                derive_mac_key = _aes_verify_krb_cred;
                break;

            default:
                throw new ArgumentException("Unknown key usage type.");
            }

            byte[] new_key = KerberosKey.DeriveAesKey(key.Key, derive_enc_key);

            int cipher_text_length = CipherText.Length - AES_CHECKSUM_SIZE;
            int remaining          = AES_BLOCK_SIZE - (cipher_text_length % AES_BLOCK_SIZE);

            decrypted = new byte[AlignBlock(cipher_text_length)];
            Array.Copy(CipherText, decrypted, cipher_text_length);

            if (remaining > 0)
            {
                byte[] decrypted_block = DecryptAESBlock(new_key, decrypted, decrypted.Length - (AES_BLOCK_SIZE * 2));
                Array.Copy(decrypted_block, AES_BLOCK_SIZE - remaining, decrypted, decrypted.Length - remaining, remaining);
            }

            SwapEndBlocks(decrypted);

            AesManaged aes = new AesManaged();

            aes.Mode    = CipherMode.CBC;
            aes.Padding = PaddingMode.None;
            aes.Key     = new_key;
            aes.IV      = new byte[16];
            var dec = aes.CreateDecryptor();

            dec.TransformBlock(decrypted, 0, decrypted.Length, decrypted, 0);

            // Obviously not a secure check. This is for information only.
            HMACSHA1 hmac = new HMACSHA1(KerberosKey.DeriveAesKey(key.Key, derive_mac_key));

            byte[] hash = hmac.ComputeHash(decrypted, 0, cipher_text_length);
            for (int i = 0; i < AES_CHECKSUM_SIZE; ++i)
            {
                if (hash[i] != CipherText[cipher_text_length + i])
                {
                    return(false);
                }
            }
            Array.Copy(decrypted, AES_CONFOUNDER_SIZE, decrypted, 0, cipher_text_length - AES_CONFOUNDER_SIZE);
            Array.Resize(ref decrypted, cipher_text_length - AES_CONFOUNDER_SIZE);
            return(true);
        }
Beispiel #9
0
        internal static bool Parse(KerberosEncryptedData orig_data, byte[] decrypted, out KerberosEncryptedData ticket)
        {
            ticket = null;
            try
            {
                DERValue[] values = DERParser.ParseData(decrypted, 0);
                if (values.Length != 1)
                {
                    return(false);
                }
                DERValue value = values[0];
                if (!value.CheckApplication(27) || !value.HasChildren())
                {
                    return(false);
                }
                if (!value.Children[0].CheckSequence())
                {
                    return(false);
                }
                var ret = new KerberosAPReplyEncryptedPart(orig_data);
                foreach (var next in value.Children[0].Children)
                {
                    if (next.Type != DERTagType.ContextSpecific)
                    {
                        return(false);
                    }
                    switch (next.Tag)
                    {
                    case 0:
                        ret.ClientTime = next.ReadChildGeneralizedTime();
                        break;

                    case 1:
                        ret.ClientUSec = next.ReadChildInteger();
                        break;

                    case 2:
                        if (!next.HasChildren())
                        {
                            return(false);
                        }
                        ret.SubKey = KerberosKey.Parse(next.Children[0], string.Empty, new KerberosPrincipalName());
                        break;

                    case 3:
                        ret.SequenceNumber = next.ReadChildInteger();
                        break;

                    default:
                        return(false);
                    }
                }
                ticket = ret;
            }
            catch (InvalidDataException)
            {
                return(false);
            }
            catch (EndOfStreamException)
            {
                return(false);
            }
            return(true);
        }
Beispiel #10
0
        internal static bool Parse(KerberosTicket orig_ticket, byte[] decrypted, KerberosKeySet keyset, out KerberosTicket ticket)
        {
            ticket = null;
            try
            {
                DERValue[] values = DERParser.ParseData(decrypted, 0);
                if (values.Length != 1)
                {
                    return(false);
                }
                DERValue value = values[0];
                if (!value.CheckApplication(3) || !value.HasChildren())
                {
                    return(false);
                }
                if (!value.Children[0].CheckSequence())
                {
                    return(false);
                }
                var ret = new KerberosTicketDecrypted(orig_ticket);
                foreach (var next in value.Children[0].Children)
                {
                    if (next.Type != DERTagType.ContextSpecific)
                    {
                        return(false);
                    }
                    switch (next.Tag)
                    {
                    case 0:
                        ret.Flags = ConvertTicketFlags(next.ReadChildBitString());
                        break;

                    case 1:
                        if (!next.HasChildren())
                        {
                            return(false);
                        }
                        ret.Key = KerberosKey.Parse(next.Children[0], orig_ticket.Realm, orig_ticket.ServerName);
                        keyset.Add(ret.Key);
                        break;

                    case 2:
                        ret.ClientRealm = next.ReadChildGeneralString();
                        break;

                    case 3:
                        if (!next.Children[0].CheckSequence())
                        {
                            return(false);
                        }
                        ret.ClientName = KerberosPrincipalName.Parse(next.Children[0]);
                        break;

                    case 4:
                        if (!next.HasChildren())
                        {
                            return(false);
                        }
                        ret.TransitedType = KerberosTransitedEncoding.Parse(next.Children[0]);
                        break;

                    case 5:
                        ret.AuthTime = next.ReadChildGeneralizedTime();
                        break;

                    case 6:
                        ret.StartTime = next.ReadChildGeneralizedTime();
                        break;

                    case 7:
                        ret.EndTime = next.ReadChildGeneralizedTime();
                        break;

                    case 8:
                        ret.RenewTill = next.ReadChildGeneralizedTime();
                        break;

                    case 9:
                        if (!next.HasChildren())
                        {
                            return(false);
                        }
                        ret.HostAddresses = KerberosHostAddress.ParseSequence(next.Children[0]);
                        break;

                    case 10:
                        if (!next.HasChildren())
                        {
                            return(false);
                        }
                        ret.AuthorizationData = KerberosAuthorizationData.ParseSequence(next.Children[0]);
                        break;

                    default:
                        return(false);
                    }
                }
                ticket = ret;
            }
            catch (InvalidDataException)
            {
                return(false);
            }
            catch (EndOfStreamException)
            {
                return(false);
            }
            return(true);
        }