public static byte[] authenticatedEncryption(CosemParameters parameters, byte[] data)
        {
            if (parameters.securityType == SecurityType.NONE)
            {
                return(data);
            }
            int ivCounter = parameters.getInvocationCounter();
            int sc        = 0;

            switch (parameters.securityType)
            {
            case SecurityType.AUTHENTICATION:
                sc = SC_AUTHENTICATION;
                byte[] authData = new byte[parameters.ak.Length + data.Length + 1];
                authData[0] = SC_AUTHENTICATION;
                Array.Copy(parameters.ak, 0, authData, 1, parameters.ak.Length);
                Array.Copy(data, 0, authData, parameters.ak.Length + 1, data.Length);
                byte[] mac   = aesGcm(new byte[0], authData, parameters, ivCounter);
                byte[] data_ = new byte[data.Length + mac.Length];
                Array.Copy(data, 0, data_, 0, data.Length);
                Array.Copy(mac, 0, data_, data.Length, mac.Length);
                data = data_;
                break;

            case SecurityType.AUTHENTICATION_ENCRYPTION:
                sc          = SC_AUTHENTICATION_ENCRYPTION;
                authData    = new byte[parameters.ak.Length + 1];
                authData[0] = SC_AUTHENTICATION_ENCRYPTION;
                Array.Copy(parameters.ak, 0, authData, 1, parameters.ak.Length);
                data = aesGcm(data, authData, parameters, ivCounter);
                break;

            case SecurityType.ENCRYPTION:
                sc   = SC_ENCRYPTION;
                data = aesGcm(data, new byte[0], parameters, ivCounter);
                break;

            default:
                throw new System.InvalidOperationException();
            }

            try
            {
                System.IO.MemoryStream stream = new System.IO.MemoryStream();
                stream.WriteByte((byte)sc);
                stream.WriteByte((byte)(ivCounter >> 24));
                stream.WriteByte((byte)(ivCounter >> 16));
                stream.WriteByte((byte)(ivCounter >> 8));
                stream.WriteByte((byte)(ivCounter));
                stream.Write(data, 0, data.Length);
                return(stream.ToArray());
            }
            catch (IOException)
            {
                throw new DlmsException(DlmsException.DlmsExceptionReason.INTERNAL_ERROR);
            }
        }
        internal static byte[] processChallanger(CosemParameters parameters, CosemConnection connection)
        {
            try
            {
                switch (parameters.authenticationType.innerEnumValue)
                {
                case AuthenticationType.InnerEnum.PUBLIC:
                case AuthenticationType.InnerEnum.LLS:
                    throw new System.InvalidOperationException();

                case AuthenticationType.InnerEnum.HLS:
                    return(aes128(connection.challengeServerToClient, parameters.llsHlsSecret));

                case AuthenticationType.InnerEnum.HLS_MD5:
                    return(md5(connection.challengeServerToClient, parameters.llsHlsSecret));

                case AuthenticationType.InnerEnum.HLS_SHA1:
                    return(sha1(connection.challengeServerToClient, parameters.llsHlsSecret));

                case AuthenticationType.InnerEnum.HLS_GMAC:
                    int ivCounter = parameters.getInvocationCounter();
                    System.IO.MemoryStream data = new System.IO.MemoryStream();
                    data.WriteByte(SC_AUTHENTICATION);
                    data.Write(parameters.ak, 0, parameters.ak.Length);
                    data.Write(connection.challengeServerToClient, 0, connection.challengeServerToClient.Length);
                    System.IO.MemoryStream stream = new System.IO.MemoryStream();
                    stream.WriteByte(SC_AUTHENTICATION);
                    stream.WriteByte((byte)(ivCounter >> 24));
                    stream.WriteByte((byte)(ivCounter >> 16));
                    stream.WriteByte((byte)(ivCounter >> 8));
                    stream.WriteByte((byte)(ivCounter));
                    byte[] aux = Security.aesGcm(new byte[0], data.ToArray(), parameters, ivCounter);
                    stream.Write(aux, 0, aux.Length);
                    return(stream.ToArray());

                default:
                    throw new System.ArgumentException();
                }
            }
            catch (IOException)
            {
                throw new DlmsException(DlmsException.DlmsExceptionReason.INTERNAL_ERROR);
            }
        }