Ejemplo n.º 1
0
        private static void CaptureArray(GXDLMSServer server, GXByteBuffer tmp, GXByteBuffer bb, int index)
        {
            //Skip type.
            tmp.GetUInt8();
            int cnt = GXCommon.GetObjectCount(tmp);

            for (int pos = 0; pos != cnt; ++pos)
            {
                if (index == -1 || index == pos)
                {
                    DataType dt = (DataType)tmp.GetUInt8(tmp.Position);
                    if (dt == DataType.Structure || dt == DataType.Array)
                    {
                        CaptureArray(server, tmp, bb, -1);
                    }
                    else
                    {
                        CaptureValue(server, tmp, bb);
                    }
                    if (index == pos)
                    {
                        break;
                    }
                }
            }
        }
Ejemplo n.º 2
0
        private static void HanleSetRequestWithDataBlock(GXDLMSSettings settings, GXDLMSServer server, GXByteBuffer data, GXDLMSLNParameters p, GXByteBuffer replyData, GXDLMSTranslatorStructure xml)
        {
            GXDataInfo reply = new GXDataInfo();

            p.multipleBlocks = data.GetUInt8() == 0;
            UInt32 blockNumber = data.GetUInt32();

            if (blockNumber != settings.BlockIndex)
            {
                Debug.WriteLine("HanleSetRequestWithDataBlock failed. Invalid block number. " + settings.BlockIndex + "/" + blockNumber);
                p.status = (byte)ErrorCode.DataBlockNumberInvalid;
            }
            else
            {
                int size     = GXCommon.GetObjectCount(data);
                int realSize = data.Size - data.Position;
                if (size != realSize)
                {
                    Debug.WriteLine("HanleSetRequestWithDataBlock failed. Invalid block size.");
                    p.status = (byte)ErrorCode.DataBlockUnavailable;
                }
                server.transaction.data.Set(data);
                //If all data is received.
                if (!p.multipleBlocks)
                {
                    try
                    {
                        object value = GXCommon.GetData(settings, server.transaction.data, reply);
                        if (value is byte[])
                        {
                            DataType dt = (server.transaction.targets[0].Target as IGXDLMSBase).GetDataType(server.transaction.targets[0].Index);
                            if (dt != DataType.None && dt != DataType.OctetString)
                            {
                                value = GXDLMSClient.ChangeType((byte[])value, dt, settings.UseUtc2NormalTime);
                            }
                        }
                        server.transaction.targets[0].Value = value;
                        server.NotifyWrite(server.transaction.targets);
                        if (!server.transaction.targets[0].Handled && !p.multipleBlocks)
                        {
                            (server.transaction.targets[0].Target as IGXDLMSBase).SetValue(settings, server.transaction.targets[0]);
                            server.NotifyPostWrite(server.transaction.targets);
                        }
                    }
                    catch (Exception)
                    {
                        p.status = (byte)ErrorCode.HardwareFault;
                    }
                    finally
                    {
                        server.transaction = null;
                    }
                    settings.ResetBlockIndex();
                }
            }
            p.multipleBlocks = true;
        }
Ejemplo n.º 3
0
        private static void UpdateTemplateDescription(GXByteBuffer columns, GXByteBuffer data, int index)
        {
            DataType ch    = (DataType)data.GetUInt8();
            int      count = GXCommon.GetObjectCount(data);

            if (index == -1)
            {
                columns.SetUInt8(ch);
                if (ch == DataType.Array)
                {
                    columns.SetUInt16((UInt16)count);
                }
                else
                {
                    columns.SetUInt8((byte)count);
                }
            }
            GXDataInfo info = new GXDataInfo();

            for (int pos = 0; pos < count; ++pos)
            {
                //If all data is captured.
                if (index == -1 || pos == index)
                {
                    DataType dt = (DataType)data.GetUInt8(data.Position);
                    if (dt == DataType.Array || dt == DataType.Structure)
                    {
                        UpdateTemplateDescription(columns, data, -1);
                        if (ch == DataType.Array)
                        {
                            break;
                        }
                    }
                    else
                    {
                        info.Clear();
                        columns.SetUInt8((byte)dt);
                        //Get data.
                        GXCommon.GetData(null, data, info);
                    }
                    if (index == pos)
                    {
                        break;
                    }
                }
            }
        }
Ejemplo n.º 4
0
        /// <summary>
        /// Test is x509 file certified by the certifier.
        /// </summary>
        /// <param name="certifier">Public key of the certifier.</param>
        /// <returns>True, if certifier has certified the certificate.</returns>
        public bool IsCertified(GXPublicKey certifier)
        {
            if (certifier == null)
            {
                throw new ArgumentNullException(nameof(certifier));
            }
            //Get raw data
            GXByteBuffer tmp2 = new GXByteBuffer();

            tmp2.Set(Encoded);
            GXAsn1Converter.GetNext(tmp2);
            tmp2.Size     = tmp2.Position;
            tmp2.Position = 1;
            GXCommon.GetObjectCount(tmp2);
            GXEcdsa        e    = new GXEcdsa(certifier);
            GXAsn1Sequence tmp3 = (GXAsn1Sequence)GXAsn1Converter.FromByteArray(Signature);
            GXByteBuffer   bb   = new GXByteBuffer();
            int            size = SignatureAlgorithm == HashAlgorithm.Sha256WithEcdsa ? 32 : 48;

            //Some implementations might add extra byte. It must removed.
            bb.Set(((GXAsn1Integer)tmp3[0]).Value, ((GXAsn1Integer)tmp3[0]).Value.Length == size ? 0 : 1, size);
            bb.Set(((GXAsn1Integer)tmp3[1]).Value, ((GXAsn1Integer)tmp3[1]).Value.Length == size ? 0 : 1, size);
            return(e.Verify(bb.Array(), tmp2.SubArray(tmp2.Position, tmp2.Available)));
        }
Ejemplo n.º 5
0
        /// <summary>
        /// Decrypt data.
        /// </summary>
        /// <param name="p">Decryption parameters</param>
        /// <returns>Decrypted data.</returns>
        public static byte[] DecryptAesGcm(AesGcmParameter p, GXByteBuffer data)
        {
            if (data == null || data.Size < 2)
            {
                throw new ArgumentOutOfRangeException("cryptedData");
            }
            byte[]  tmp;
            int     len;
            Command cmd = (Command)data.GetUInt8();

            switch (cmd)
            {
            case Command.GeneralGloCiphering:
            case Command.GeneralDedCiphering:
                len = GXCommon.GetObjectCount(data);
                if (len != 0)
                {
                    p.SystemTitle = new byte[len];
                    data.Get(p.SystemTitle);
                    if (p.Xml != null && p.Xml.Comments)
                    {
                        p.Xml.AppendComment(GXCommon.SystemTitleToString(Standard.DLMS, p.SystemTitle));
                    }
                }
                if (p.SystemTitle == null || p.SystemTitle.Length != 8)
                {
                    if (p.Xml == null)
                    {
                        throw new ArgumentNullException("Invalid sender system title.");
                    }
                    else
                    {
                        p.Xml.AppendComment("Invalid sender system title.");
                    }
                }
                break;

            case Command.GeneralCiphering:
            case Command.GloInitiateRequest:
            case Command.GloInitiateResponse:
            case Command.GloReadRequest:
            case Command.GloReadResponse:
            case Command.GloWriteRequest:
            case Command.GloWriteResponse:
            case Command.GloGetRequest:
            case Command.GloGetResponse:
            case Command.GloSetRequest:
            case Command.GloSetResponse:
            case Command.GloMethodRequest:
            case Command.GloMethodResponse:
            case Command.GloEventNotification:
            case Command.DedInitiateRequest:
            case Command.DedInitiateResponse:
            case Command.DedGetRequest:
            case Command.DedGetResponse:
            case Command.DedSetRequest:
            case Command.DedSetResponse:
            case Command.DedMethodRequest:
            case Command.DedMethodResponse:
            case Command.DedEventNotification:
            case Command.DedReadRequest:
            case Command.DedReadResponse:
            case Command.DedWriteRequest:
            case Command.DedWriteResponse:
            case Command.GloConfirmedServiceError:
            case Command.DedConfirmedServiceError:
                break;

            default:
                throw new ArgumentOutOfRangeException("cryptedData");
            }
            int    value         = 0;
            UInt64 transactionId = 0;

            if (cmd == Command.GeneralCiphering)
            {
                len = GXCommon.GetObjectCount(data);
                tmp = new byte[len];
                data.Get(tmp);
                GXByteBuffer t = new GXByteBuffer(tmp);
                transactionId = t.GetUInt64();
                len           = GXCommon.GetObjectCount(data);
                if (len != 0)
                {
                    tmp = new byte[len];
                    data.Get(tmp);
                    p.SystemTitle = tmp;
                }
                if (p.SystemTitle == null || p.SystemTitle.Length != 8)
                {
                    if (p.Xml == null)
                    {
                        throw new ArgumentNullException("Invalid sender system title.");
                    }
                    else
                    {
                        p.Xml.AppendComment("Invalid sender system title.");
                    }
                }
                len = GXCommon.GetObjectCount(data);
                tmp = new byte[len];
                data.Get(tmp);
                p.RecipientSystemTitle = tmp;
                // Get date time.
                len = GXCommon.GetObjectCount(data);
                if (len != 0)
                {
                    tmp = new byte[len];
                    data.Get(tmp);
                    p.DateTime = tmp;
                }
                // other-information
                len = data.GetUInt8();
                if (len != 0)
                {
                    tmp = new byte[len];
                    data.Get(tmp);
                    p.OtherInformation = tmp;
                }
                // KeyInfo OPTIONAL
                len = data.GetUInt8();
                // AgreedKey CHOICE tag.
                data.GetUInt8();
                // key-parameters
                len             = data.GetUInt8();
                value           = data.GetUInt8();
                p.KeyParameters = value;
                if (value == 1)
                {
                    // KeyAgreement.ONE_PASS_DIFFIE_HELLMAN
                    // key-ciphered-data
                    len = GXCommon.GetObjectCount(data);
                    tmp = new byte[len];
                    data.Get(tmp);
                    p.KeyCipheredData = tmp;
                }
                else if (value == 2)
                {
                    // KeyAgreement.STATIC_UNIFIED_MODEL
                    len = GXCommon.GetObjectCount(data);
                    if (len != 0)
                    {
                        throw new ArgumentException("Invalid key parameters");
                    }
                }
                else
                {
                    throw new ArgumentException("key-parameters");
                }
            }
            len = GXCommon.GetObjectCount(data);
            p.CipheredContent = data.Remaining();
            byte sc = (byte)data.GetUInt8();

            Enums.Security security = (Enums.Security)(sc & 0x30);
            if ((sc & 0x80) != 0)
            {
                System.Diagnostics.Debug.WriteLine("Compression is used.");
            }
            if ((sc & 0x40) != 0)
            {
                System.Diagnostics.Debug.WriteLine("Error: Key_Set is used.");
            }
            if ((sc & 0x20) != 0)
            {
                System.Diagnostics.Debug.WriteLine("Encryption is applied.");
            }

            SecuritySuite ss = (SecuritySuite)(sc & 0x3);

            p.Security = (byte)security;
            UInt32 invocationCounter = data.GetUInt32();

            p.InvocationCounter = invocationCounter;
            if (ss == SecuritySuite.Version2)
            {
                throw new NotImplementedException("Security Suite 2 is not implemented.");
            }
            System.Diagnostics.Debug.WriteLine("Decrypt settings: " + p.ToString());
            System.Diagnostics.Debug.WriteLine("Encrypted: " + GXCommon.ToHex(data.Data,
                                                                              false, data.Position, data.Size - data.Position));
            byte[] tag = new byte[12];
            byte[] encryptedData;
            int    length;

            if (security == Enums.Security.Authentication)
            {
                length        = data.Size - data.Position - 12;
                encryptedData = new byte[length];
                data.Get(encryptedData);
                data.Get(tag);
                // Check tag.
                EncryptAesGcm(p, encryptedData);
                if (!GXDLMSChipperingStream.TagsEquals(tag, p.CountTag))
                {
                    if (transactionId != 0)
                    {
                        p.InvocationCounter = transactionId;
                    }
                    if (p.Xml == null)
                    {
                        throw new GXDLMSException("Decrypt failed. Invalid tag.");
                    }
                    else
                    {
                        p.Xml.AppendComment("Decrypt failed. Invalid tag.");
                    }
                }
                return(encryptedData);
            }
            byte[] ciphertext = null;
            if (security == Enums.Security.Encryption)
            {
                length     = data.Size - data.Position;
                ciphertext = new byte[length];
                data.Get(ciphertext);
            }
            else if (security == Enums.Security.AuthenticationEncryption)
            {
                length     = data.Size - data.Position - 12;
                ciphertext = new byte[length];
                data.Get(ciphertext);
                data.Get(tag);
            }
            byte[] aad = GetAuthenticatedData(p, ciphertext),
            iv = GetNonse(invocationCounter, p.SystemTitle);
            GXDLMSChipperingStream gcm = new GXDLMSChipperingStream((byte)security, true,
                                                                    p.BlockCipherKey, aad, iv, tag);

            gcm.Write(ciphertext);
            if (transactionId != 0)
            {
                p.InvocationCounter = transactionId;
            }
            return(gcm.FlushFinalBlock());
        }
Ejemplo n.º 6
0
        /// <summary>
        /// Decrypt data.
        /// </summary>
        /// <param name="p">Decryption parameters</param>
        /// <returns>Decrypted data.</returns>
        public static byte[] DecryptAesGcm(AesGcmParameter p, GXByteBuffer data)
        {
            if (data == null || data.Size < 2)
            {
                throw new ArgumentOutOfRangeException("cryptedData");
            }
            byte[]  tmp;
            int     len;
            Command cmd = (Command)data.GetUInt8();

            switch (cmd)
            {
            case Command.GeneralGloCiphering:
                len = GXCommon.GetObjectCount(data);
                if (len != 0)
                {
                    p.SystemTitle = new byte[len];
                    data.Get(p.SystemTitle);
                }
                break;

            case Command.GeneralCiphering:
            case Command.GloInitiateRequest:
            case Command.GloInitiateResponse:
            case Command.GloReadRequest:
            case Command.GloReadResponse:
            case Command.GloWriteRequest:
            case Command.GloWriteResponse:
            case Command.GloGetRequest:
            case Command.GloGetResponse:
            case Command.GloSetRequest:
            case Command.GloSetResponse:
            case Command.GloMethodRequest:
            case Command.GloMethodResponse:
            case Command.GloEventNotificationRequest:
                break;

            default:
                throw new ArgumentOutOfRangeException("cryptedData");
            }
            int    value         = 0;
            UInt64 transactionId = 0;

            if (cmd == Command.GeneralCiphering)
            {
                len = GXCommon.GetObjectCount(data);
                tmp = new byte[len];
                data.Get(tmp);
                GXByteBuffer t = new GXByteBuffer(tmp);
                transactionId = t.GetUInt64();
                len           = GXCommon.GetObjectCount(data);
                tmp           = new byte[len];
                data.Get(tmp);
                p.SystemTitle = tmp;
                len           = GXCommon.GetObjectCount(data);
                tmp           = new byte[len];
                data.Get(tmp);
                p.RecipientSystemTitle = tmp;
                // Get date time.
                len = GXCommon.GetObjectCount(data);
                if (len != 0)
                {
                    tmp = new byte[len];
                    data.Get(tmp);
                    p.DateTime = tmp;
                }
                // other-information
                len = data.GetUInt8();
                if (len != 0)
                {
                    tmp = new byte[len];
                    data.Get(tmp);
                    p.OtherInformation = tmp;
                }
                // KeyInfo OPTIONAL
                len = data.GetUInt8();
                // AgreedKey CHOICE tag.
                data.GetUInt8();
                // key-parameters
                len             = data.GetUInt8();
                value           = data.GetUInt8();
                p.KeyParameters = value;
                if (value == 1)
                {
                    // KeyAgreement.ONE_PASS_DIFFIE_HELLMAN
                    // key-ciphered-data
                    len = GXCommon.GetObjectCount(data);
                    tmp = new byte[len];
                    data.Get(tmp);
                    p.KeyCipheredData = tmp;
                }
                else if (value == 2)
                {
                    // KeyAgreement.STATIC_UNIFIED_MODEL
                    len = GXCommon.GetObjectCount(data);
                    if (len != 0)
                    {
                        throw new ArgumentException("Invalid key parameters");
                    }
                }
                else
                {
                    throw new ArgumentException("key-parameters");
                }
            }
            len = GXCommon.GetObjectCount(data);
            p.CipheredContent = data.Remaining();
            byte sc = (byte)data.GetUInt8();

            Enums.Security security = (Enums.Security)(sc & 0x30);
            SecuritySuite  ss       = (SecuritySuite)(sc & 0x3);

            p.Security = security;
            UInt32 invocationCounter = data.GetUInt32();

            p.InvocationCounter = invocationCounter;
            if (ss != SecuritySuite.AesGcm128)
            {
                throw new NotImplementedException("Security Suite 1 is not implemented.");
            }
            System.Diagnostics.Debug.WriteLine("Decrypt settings: " + p.ToString());
            System.Diagnostics.Debug.WriteLine("Encrypted: " + GXCommon.ToHex(data.Data,
                                                                              false, data.Position, data.Size - data.Position));
            byte[] tag = new byte[12];
            byte[] encryptedData;
            int    length;

            if (security == Enums.Security.Authentication)
            {
                length        = data.Size - data.Position - 12;
                encryptedData = new byte[length];
                data.Get(encryptedData);
                data.Get(tag);
                // Check tag.
                EncryptAesGcm(p, encryptedData);
                if (!GXDLMSChipperingStream.TagsEquals(tag, p.CountTag))
                {
                    if (transactionId != 0)
                    {
                        p.InvocationCounter = transactionId;
                    }
                    throw new GXDLMSException("Decrypt failed. Invalid tag.");
                }
                return(encryptedData);
            }
            byte[] ciphertext = null;
            if (security == Enums.Security.Encryption)
            {
                length     = data.Size - data.Position;
                ciphertext = new byte[length];
                data.Get(ciphertext);
            }
            else if (security == Enums.Security.AuthenticationEncryption)
            {
                length     = data.Size - data.Position - 12;
                ciphertext = new byte[length];
                data.Get(ciphertext);
                data.Get(tag);
            }
            byte[] aad = GetAuthenticatedData(p, ciphertext),
            iv = GetNonse(invocationCounter, p.SystemTitle);
            GXDLMSChipperingStream gcm = new GXDLMSChipperingStream(security, true,
                                                                    p.BlockCipherKey, aad, iv, tag);

            gcm.Write(ciphertext);
            if (transactionId != 0)
            {
                p.InvocationCounter = transactionId;
            }
            return(gcm.FlushFinalBlock());

            /*
             * len = Gurux.DLMS.Internal.GXCommon.GetObjectCount(data);
             * p.Security = (Gurux.DLMS.Enums.Security)data.GetUInt8();
             * p.InvocationCounter = data.GetUInt32();
             * System.Diagnostics.Debug.WriteLine("Decrypt settings: " + p.ToString());
             * System.Diagnostics.Debug.WriteLine("Encrypted: " + GXCommon.ToHex(data.Array(), true));
             *
             * byte[] tag = new byte[12];
             * byte[] encryptedData;
             * int length;
             * if (p.Security == Gurux.DLMS.Enums.Security.Authentication)
             * {
             *  length = data.Size - data.Position - 12;
             *  encryptedData = new byte[length];
             *  data.Get(encryptedData);
             *  data.Get(tag);
             *  // Check tag.
             *  EncryptAesGcm(p, encryptedData);
             *  if (!GXDLMSChipperingStream.TagsEquals(tag, p.CountTag))
             *  {
             *      throw new GXDLMSException("Decrypt failed. Invalid tag.");
             *  }
             *  return encryptedData;
             * }
             * byte[] ciphertext = null;
             * if (p.Security == Gurux.DLMS.Enums.Security.Encryption)
             * {
             *  length = data.Size - data.Position;
             *  ciphertext = new byte[length];
             *  data.Get(ciphertext);
             * }
             * else if (p.Security == Gurux.DLMS.Enums.Security.AuthenticationEncryption)
             * {
             *  length = data.Size - data.Position - 12;
             *  ciphertext = new byte[length];
             *  data.Get(ciphertext);
             *  data.Get(tag);
             * }
             * byte[] aad = GetAuthenticatedData(p.Security, p.AuthenticationKey, ciphertext);
             * byte[] iv = GetNonse(p.InvocationCounter, p.SystemTitle);
             * GXDLMSChipperingStream gcm = new GXDLMSChipperingStream(p.Security, true, p.BlockCipherKey, aad, iv, tag);
             * gcm.Write(ciphertext);
             * ciphertext = gcm.FlushFinalBlock();
             * if (p.Security == Gurux.DLMS.Enums.Security.AuthenticationEncryption)
             * {
             *  // Check tag.
             *  EncryptAesGcm(p, ciphertext);
             *  if (!GXDLMSChipperingStream.TagsEquals(tag, p.CountTag))
             *  {
             *      //    throw new GXDLMSException("Decrypt failed. Invalid tag.");
             *  }
             * }
             * return ciphertext;
             */
        }
Ejemplo n.º 7
0
        /// <summary>
        /// Handle read request.
        /// </summary>
        /// <param name="settings">DLMS settings.</param>
        /// <param name="server">DLMS server.</param>
        /// <param name="data">Received data.</param>
        public static void HandleReadRequest(GXDLMSSettings settings, GXDLMSServer server, GXByteBuffer data, GXByteBuffer replyData, GXDLMSTranslatorStructure xml)
        {
            GXByteBuffer          bb      = new GXByteBuffer();
            int                   cnt     = 0xFF;
            byte                  type    = 0;
            List <ValueEventArgs> list    = new List <ValueEventArgs>();
            List <ValueEventArgs> reads   = new List <ValueEventArgs>();
            List <ValueEventArgs> actions = new List <ValueEventArgs>();

            //If get next frame.
            if (xml == null && data.Size == 0)
            {
                if (server.transaction != null)
                {
                    return;
                }
                bb.Set(replyData);
                replyData.Clear();
                foreach (ValueEventArgs it in server.transaction.targets)
                {
                    list.Add(it);
                }
            }
            else
            {
                cnt = GXCommon.GetObjectCount(data);
                if (xml != null)
                {
                    xml.AppendStartTag(Command.ReadRequest, "Qty", xml.IntegerToHex(cnt, 2));
                }

                for (int pos = 0; pos != cnt; ++pos)
                {
                    type = data.GetUInt8();
                    if (type == (byte)VariableAccessSpecification.VariableName ||
                        type == (byte)VariableAccessSpecification.ParameterisedAccess)
                    {
                        HandleRead(settings, server, type, data, list, reads, actions, replyData, xml);
                    }
                    else if (type == (byte)VariableAccessSpecification.BlockNumberAccess)
                    {
                        HandleReadBlockNumberAccess(settings, server, data, replyData, xml);
                        if (xml != null)
                        {
                            xml.AppendEndTag(Command.ReadRequest);
                        }
                        return;
                    }
                    else if (type == (byte)VariableAccessSpecification.ReadDataBlockAccess)
                    {
                        HandleReadDataBlockAccess(settings, server, Command.ReadResponse, data, cnt, replyData, xml);
                        if (xml != null)
                        {
                            xml.AppendEndTag(Command.ReadRequest);
                        }
                        return;
                    }
                    else
                    {
                        ReturnSNError(settings, server, Command.ReadResponse, ErrorCode.ReadWriteDenied, replyData);
                        if (xml != null)
                        {
                            xml.AppendEndTag(Command.ReadRequest);
                        }
                        return;
                    }
                }
                if (reads.Count != 0)
                {
                    server.NotifyRead(reads.ToArray());
                }

                if (actions.Count != 0)
                {
                    server.NotifyAction(actions.ToArray());
                }
            }
            if (xml != null)
            {
                xml.AppendEndTag(Command.ReadRequest);
                return;
            }

            byte requestType = (byte)GetReadData(settings, list.ToArray(), bb);

            if (reads.Count != 0)
            {
                server.NotifyPostRead(reads.ToArray());
            }

            if (actions.Count != 0)
            {
                server.NotifyPostAction(actions.ToArray());
            }

            GXDLMSSNParameters p = new GXDLMSSNParameters(settings, Command.ReadResponse, list.Count, requestType, null, bb);

            GXDLMS.GetSNPdu(p, replyData);
            if (server.transaction == null && (bb.Size != bb.Position || settings.Count != settings.Index))
            {
                reads = new List <ValueEventArgs>();
                foreach (var it in list)
                {
                    reads.Add(it);
                }
                server.transaction = new GXDLMSLongTransaction(reads.ToArray(), Command.ReadRequest, bb);
            }
            else if (server.transaction != null)
            {
                replyData.Set(bb);
                return;
            }
        }
Ejemplo n.º 8
0
        private static void HandleReadDataBlockAccess(
            GXDLMSSettings settings, GXDLMSServer server,
            Command command, GXByteBuffer data, int cnt, GXByteBuffer replyData, GXDLMSTranslatorStructure xml)
        {
            GXByteBuffer bb          = new GXByteBuffer();
            byte         lastBlock   = data.GetUInt8();
            UInt16       blockNumber = data.GetUInt16();

            if (xml != null)
            {
                if (command == Command.WriteResponse)
                {
                    xml.AppendStartTag(TranslatorTags.WriteDataBlockAccess);
                }
                else
                {
                    xml.AppendStartTag(TranslatorTags.ReadDataBlockAccess);
                }
                xml.AppendLine("<LastBlock Value=\"" + xml.IntegerToHex(lastBlock, 2) + "\" />");
                xml.AppendLine("<BlockNumber Value=\"" + xml.IntegerToHex(blockNumber, 4) + "\" />");
                if (command == Command.WriteResponse)
                {
                    xml.AppendEndTag(TranslatorTags.WriteDataBlockAccess);
                }
                else
                {
                    xml.AppendEndTag(TranslatorTags.ReadDataBlockAccess);
                }
                return;
            }
            if (blockNumber != settings.BlockIndex)
            {
                Debug.WriteLine("handleReadRequest failed. Invalid block number. " + settings.BlockIndex + "/" + blockNumber);
                bb.SetUInt8(ErrorCode.DataBlockNumberInvalid);
                GXDLMS.GetSNPdu(new GXDLMSSNParameters(settings, command, 1, (byte)SingleReadResponse.DataAccessError, bb, null), replyData);
                settings.ResetBlockIndex();
                return;
            }
            int  count = 1;
            byte type  = (byte)DataType.OctetString;

            if (command == Command.WriteResponse)
            {
                count = GXCommon.GetObjectCount(data);
                type  = data.GetUInt8();
            }
            int size     = GXCommon.GetObjectCount(data);
            int realSize = data.Size - data.Position;

            if (count != 1 || type != (byte)DataType.OctetString || size != realSize)
            {
                Debug.WriteLine("handleGetRequest failed. Invalid block size.");
                bb.SetUInt8(ErrorCode.DataBlockUnavailable);
                GXDLMS.GetSNPdu(new GXDLMSSNParameters(settings, command, cnt, (byte)SingleReadResponse.DataAccessError, bb, null), replyData);
                settings.ResetBlockIndex();
                return;
            }
            if (server.transaction == null)
            {
                server.transaction = new GXDLMSLongTransaction(null, command, data);
            }
            else
            {
                server.transaction.data.Set(data);
            }
            if (lastBlock == 0)
            {
                bb.SetUInt16(blockNumber);
                settings.IncreaseBlockIndex();
                if (command == Command.ReadResponse)
                {
                    type = (byte)SingleReadResponse.BlockNumber;
                }
                else
                {
                    type = (byte)SingleWriteResponse.BlockNumber;
                }
                GXDLMS.GetSNPdu(new GXDLMSSNParameters(settings, command, cnt, type, null, bb), replyData);
                return;
            }
            else
            {
                if (server.transaction != null)
                {
                    data.Size = 0;
                    data.Set(server.transaction.data);
                    server.transaction = null;
                }
                if (command == Command.ReadResponse)
                {
                    HandleReadRequest(settings, server, data, replyData, xml);
                }
                else
                {
                    HandleWriteRequest(settings, server, data, replyData, xml);
                }
                settings.ResetBlockIndex();
            }
        }
Ejemplo n.º 9
0
        ///<summary>
        /// Handle write request.
        ///</summary>
        public static void HandleWriteRequest(GXDLMSSettings settings, GXDLMSServer server, GXByteBuffer data,
                                              GXByteBuffer replyData, GXDLMSTranslatorStructure xml)
        {
            //Return error if connection is not established.
            if (xml == null && !settings.Connected)
            {
                replyData.Add(GXDLMSServer.GenerateConfirmedServiceError(ConfirmedServiceError.InitiateError,
                                                                         ServiceError.Service, (byte)Service.Unsupported));
                return;
            }
            short  type;
            object value;
            // Get object count.
            List <GXSNInfo> targets = new List <GXSNInfo>();
            int             cnt     = GXCommon.GetObjectCount(data);

            if (xml != null)
            {
                xml.AppendStartTag(Command.WriteRequest);
                xml.AppendStartTag(
                    TranslatorTags.ListOfVariableAccessSpecification, "Qty",
                    xml.IntegerToHex(cnt, 2));
                if (xml.OutputType == TranslatorOutputType.StandardXml)
                {
                    xml.AppendStartTag(
                        TranslatorTags.VariableAccessSpecification);
                }
            }
            GXByteBuffer results = new GXByteBuffer((ushort)cnt);

            for (int pos = 0; pos != cnt; ++pos)
            {
                type = data.GetUInt8();
                if (type == (byte)VariableAccessSpecification.VariableName)
                {
                    int sn = data.GetUInt16();
                    if (xml != null)
                    {
                        xml.AppendLine(
                            (int)Command.WriteRequest << 8
                                | (int)VariableAccessSpecification.VariableName,
                                "Value", xml.IntegerToHex(sn, 4));
                    }
                    else
                    {
                        GXSNInfo info = FindSNObject(server, sn);
                        targets.Add(info);
                        // If target is unknown.
                        if (info == null)
                        {
                            // Device reports a undefined object.
                            results.SetUInt8(ErrorCode.UndefinedObject);
                        }
                        else
                        {
                            results.SetUInt8(ErrorCode.Ok);
                        }
                    }
                }
                else if (type == (byte)VariableAccessSpecification.WriteDataBlockAccess)
                {
                    HandleReadDataBlockAccess(settings, server, Command.WriteResponse, data, cnt, replyData, xml);
                    if (xml == null)
                    {
                        return;
                    }
                }
                else
                {
                    // Device reports a HW error.
                    results.SetUInt8(ErrorCode.HardwareFault);
                }
            }

            if (xml != null)
            {
                if (xml.OutputType == TranslatorOutputType.StandardXml)
                {
                    xml.AppendEndTag(TranslatorTags.VariableAccessSpecification);
                }
                xml.AppendEndTag(
                    TranslatorTags.ListOfVariableAccessSpecification);
            }
            // Get data count.
            cnt = GXCommon.GetObjectCount(data);
            GXDataInfo di = new GXDataInfo();

            di.xml = xml;
            if (xml != null)
            {
                xml.AppendStartTag(TranslatorTags.ListOfData, "Qty", xml.IntegerToHex(cnt, 2));
            }
            for (int pos = 0; pos != cnt; ++pos)
            {
                di.Clear();
                if (xml != null)
                {
                    if (xml.OutputType == TranslatorOutputType.StandardXml)
                    {
                        xml.AppendStartTag(Command.WriteRequest,
                                           SingleReadResponse.Data);
                    }
                    value = GXCommon.GetData(settings, data, di);
                    if (!di.Complete)
                    {
                        value = GXCommon.ToHex(data.Data, false,
                                               data.Position, data.Size - data.Position);
                        xml.AppendLine(
                            GXDLMS.DATA_TYPE_OFFSET + (int)di.Type,
                            "Value", value.ToString());
                    }
                    if (xml.OutputType == TranslatorOutputType.StandardXml)
                    {
                        xml.AppendEndTag(Command.WriteRequest, SingleReadResponse.Data);
                    }
                    GXCommon.GetData(settings, data, di);
                }
                else if (results.GetUInt8(pos) == 0)
                {
                    // If object has found.
                    GXSNInfo target = targets[pos];
                    value = GXCommon.GetData(settings, data, di);
                    if (value is byte[])
                    {
                        DataType dt = target.Item.GetDataType(target.Index);
                        if (dt != DataType.None && dt != DataType.OctetString)
                        {
                            value = GXDLMSClient.ChangeType((byte[])value, dt, settings.UseUtc2NormalTime);
                        }
                    }
                    ValueEventArgs e  = new ValueEventArgs(server, target.Item, target.Index, 0, null);
                    AccessMode     am = server.NotifyGetAttributeAccess(e);
                    // If write is denied.
                    if (am != AccessMode.Write && am != AccessMode.ReadWrite)
                    {
                        results.SetUInt8((byte)pos, (byte)ErrorCode.ReadWriteDenied);
                    }
                    else
                    {
                        e.Value = value;
                        server.NotifyWrite(new ValueEventArgs[] { e });
                        if (e.Error != 0)
                        {
                            results.SetUInt8((byte)pos, (byte)e.Error);
                        }
                        else if (!e.Handled)
                        {
                            (target.Item as IGXDLMSBase).SetValue(settings, e);
                            server.NotifyPostWrite(new ValueEventArgs[] { e });
                        }
                    }
                }
            }
            if (xml != null)
            {
                xml.AppendEndTag(TranslatorTags.ListOfData);
                xml.AppendEndTag(Command.WriteRequest);
                return;
            }
            GenerateWriteResponse(settings, results, replyData);
        }
        /// <summary>
        /// Handle Information Report.
        /// </summary>
        /// <param name="settings">DLMS settings.</param>
        /// <param name="reply"></param>
        /// <returns></returns>
        public static void HandleInformationReport(GXDLMSSettings settings, GXReplyData reply, List <KeyValuePair <GXDLMSObject, int> > list)
        {
            reply.Time = DateTime.MinValue;
            int len = reply.Data.GetUInt8();

            byte[] tmp = null;
            // If date time is given.
            if (len != 0)
            {
                tmp = new byte[len];
                reply.Data.Get(tmp);
                reply.Time = (GXDateTime)GXDLMSClient.ChangeType(tmp, DataType.DateTime, settings.UseUtc2NormalTime);
            }
            byte type;
            int  count = GXCommon.GetObjectCount(reply.Data);

            if (reply.Xml != null)
            {
                reply.Xml.AppendStartTag(Command.InformationReport);
                if (reply.Time != DateTime.MinValue)
                {
                    reply.Xml.AppendComment(Convert.ToString(reply.Time));
                    if (reply.Xml.OutputType == TranslatorOutputType.SimpleXml)
                    {
                        reply.Xml.AppendLine(TranslatorTags.CurrentTime, null, GXCommon.ToHex(tmp, false));
                    }
                    else
                    {
                        reply.Xml.AppendLine(TranslatorTags.CurrentTime, null,
                                             GXCommon.GeneralizedTime(reply.Time));
                    }
                }
                reply.Xml.AppendStartTag(TranslatorTags.ListOfVariableAccessSpecification, "Qty", reply.Xml.IntegerToHex(count, 2));
            }
            for (int pos = 0; pos != count; ++pos)
            {
                type = reply.Data.GetUInt8();
                if (type == (byte)VariableAccessSpecification.VariableName)
                {
                    int sn = reply.Data.GetUInt16();
                    if (reply.Xml != null)
                    {
                        reply.Xml.AppendLine(
                            (int)Command.WriteRequest << 8
                                | (int)VariableAccessSpecification.VariableName,
                                "Value", reply.Xml.IntegerToHex(sn, 4));
                    }
                    else
                    {
                        GXSNInfo info = FindSNObject(settings.Objects, sn);
                        if (info.Item != null)
                        {
                            list.Add(new KeyValuePair <GXDLMSObject, int>(info.Item, info.Index));
                        }
                        else
                        {
                            System.Diagnostics.Debug.WriteLine(string.Format("Unknown object : {0}.", sn));
                        }
                    }
                }
            }
            if (reply.Xml != null)
            {
                reply.Xml.AppendEndTag(TranslatorTags.ListOfVariableAccessSpecification);
                reply.Xml.AppendStartTag(TranslatorTags.ListOfData, "Qty", reply.Xml.IntegerToHex(count, 2));
            }
            //Get values.
            count = GXCommon.GetObjectCount(reply.Data);
            GXDataInfo di = new GXDataInfo();

            di.xml = reply.Xml;
            for (int pos = 0; pos != count; ++pos)
            {
                di.Clear();
                if (reply.Xml != null)
                {
                    GXCommon.GetData(settings, reply.Data, di);
                }
                else
                {
                    ValueEventArgs v = new ValueEventArgs(list[pos].Key, list[pos].Value, 0, null);
                    v.Value = GXCommon.GetData(settings, reply.Data, di);
                    (list[pos].Key as IGXDLMSBase).SetValue(settings, v);
                }
            }
            if (reply.Xml != null)
            {
                reply.Xml.AppendEndTag(TranslatorTags.ListOfData);
                reply.Xml.AppendEndTag(Command.InformationReport);
            }
        }
Ejemplo n.º 11
0
        private static void GetValue(GXByteBuffer bb, IList <object> objects, GXAsn1Settings s)
        {
            int            len;
            short          type;
            IList <object> tmp;

            byte[] tmp2;
            type = bb.GetUInt8();
            len  = GXCommon.GetObjectCount(bb);
            if (len > bb.Available)
            {
                throw new OutOfMemoryException("GXAsn1Converter.GetValue");
            }
            int connectPos = 0;

            if (s != null)
            {
                connectPos = s.XmlLength;
            }
            int    start     = bb.Position;
            string tagString = null;

            if (s != null)
            {
                s.AppendSpaces();
                if (type == (byte)BerType.Integer)
                {
                    if (len == 1 || len == 2 || len == 4 || len == 8)
                    {
                        tagString = s.GetTag((short)-len);
                    }
                    else
                    {
                        tagString = s.GetTag((byte)BerType.Integer);
                    }
                }
                else
                {
                    tagString = s.GetTag(type);
                }
                s.Append("<" + tagString + ">");
            }

            switch (type)
            {
            case (byte)(BerType.Constructed | BerType.Context):
            case ((byte)(BerType.Constructed | BerType.Context) | 1):
            case ((byte)(BerType.Constructed | BerType.Context) | 2):
            case ((byte)(BerType.Constructed | BerType.Context) | 3):
            case ((byte)(BerType.Constructed | BerType.Context) | 4):
                if (s != null)
                {
                    s.Increase();
                }
                tmp = new GXAsn1Context()
                {
                    Index = type & 0xF
                };
                objects.Add(tmp);
                while (bb.Position < start + len)
                {
                    GetValue(bb, tmp, s);
                }
                if (s != null)
                {
                    s.Decrease();
                }
                break;

            case (byte)(BerType.Constructed | BerType.Sequence):
                if (s != null)
                {
                    s.Increase();
                }
                tmp = new GXAsn1Sequence();
                objects.Add(tmp);
                int cnt = 0;
                while (bb.Position < start + len)
                {
                    ++cnt;
                    GetValue(bb, tmp, s);
                }
                if (s != null)
                {
                    // Append comment.
                    s.AppendComment(connectPos, Convert.ToString(cnt) + " elements.");
                    s.Decrease();
                }
                break;

            case (byte)(BerType.Constructed | BerType.Set):
                if (s != null)
                {
                    s.Increase();
                }
                tmp = new List <object>();
                GetValue(bb, tmp, s);
                if (tmp[0] is GXAsn1Sequence)
                {
                    tmp = (GXAsn1Sequence)tmp[0];
                    objects.Add(new KeyValuePair <object, object>(tmp[0], tmp[1]));
                }
                else
                {
                    KeyValuePair <object, object> e = new KeyValuePair <object, object>(tmp, null);
                    objects.Add(e);
                }
                if (s != null)
                {
                    s.Decrease();
                }
                break;

            case (byte)BerType.ObjectIdentifier:
                GXAsn1ObjectIdentifier oi = new GXAsn1ObjectIdentifier(bb, len);
                objects.Add(oi);
                if (s != null)
                {
                    string str = oi.Description;
                    if (str != null)
                    {
                        s.AppendComment(connectPos, str);
                    }
                    s.Append(oi.ToString());
                }

                break;

            case (byte)BerType.PrintableString:
                objects.Add(bb.GetString(len));
                if (s != null)
                {
                    s.Append(Convert.ToString(objects[objects.Count - 1]));
                }

                break;

            case (byte)BerType.Utf8StringTag:
                objects.Add(new GXAsn1Utf8String(bb.GetString(bb.Position, len)));
                bb.Position = bb.Position + len;
                if (s != null)
                {
                    s.Append(Convert.ToString(objects[objects.Count - 1]));
                }

                break;

            case (byte)BerType.Ia5String:
                objects.Add(new GXAsn1Ia5String(bb.GetString(len)));
                if (s != null)
                {
                    s.Append(Convert.ToString(objects[objects.Count - 1]));
                }
                break;

            case (byte)BerType.Integer:
                if (len == 1)
                {
                    objects.Add(bb.GetInt8());
                }
                else if (len == 2)
                {
                    objects.Add(bb.GetInt16());
                }
                else if (len == 4)
                {
                    objects.Add(bb.GetInt32());
                }
                else
                {
                    tmp2 = new byte[len];
                    bb.Get(tmp2);
                    objects.Add(new GXAsn1Integer(tmp2));
                }
                if (s != null)
                {
                    s.Append(Convert.ToString(objects[objects.Count - 1]));
                }
                break;

            case (byte)BerType.Null:
                objects.Add(null);
                break;

            case (byte)BerType.BitString:
                GXAsn1BitString tmp3 = new GXAsn1BitString(bb.SubArray(bb.Position, len));
                objects.Add(tmp3);
                bb.Position = bb.Position + len;
                if (s != null)
                {
                    // Append comment.
                    s.AppendComment(connectPos, Convert.ToString(tmp3.Length) + " bit.");
                    s.Append(tmp3.asString());
                }
                break;

            case (byte)BerType.UtcTime:
                tmp2 = new byte[len];
                bb.Get(tmp2);
                objects.Add(GetUtcTime(ASCIIEncoding.ASCII.GetString(tmp2)));
                if (s != null)
                {
                    s.Append(((DateTimeOffset)objects[objects.Count - 1]).UtcDateTime.ToString("yyyy-MM-dd HH:mm", CultureInfo.InvariantCulture));
                }
                break;

            case (byte)BerType.GeneralizedTime:
                tmp2 = new byte[len];
                bb.Get(tmp2);
                objects.Add(GXCommon.GetGeneralizedTime(ASCIIEncoding.ASCII.GetString(tmp2)));
                if (s != null)
                {
                    s.Append(Convert.ToString(objects[objects.Count - 1]));
                }
                break;

            case (byte)BerType.Context:
            case (byte)BerType.Context | 1:
            case (byte)BerType.Context | 2:
            case (byte)BerType.Context | 3:
                tmp = new GXAsn1Context()
                {
                    Constructed = false, Index = type & 0xF
                };
                tmp2 = new byte[len];
                bb.Get(tmp2);
                tmp.Add(tmp2);
                objects.Add(tmp);
                if (s != null)
                {
                    s.Append(GXCommon.ToHex(tmp2, false));
                }
                break;

            case (byte)BerType.OctetString:
                int t = bb.GetUInt8(bb.Position);
                switch (t)
                {
                case (byte)(BerType.Constructed | BerType.Sequence):
                case (byte)BerType.BitString:
                    if (s != null)
                    {
                        s.Increase();
                    }
                    GetValue(bb, objects, s);
                    if (s != null)
                    {
                        s.Decrease();
                    }
                    break;

                default:
                    tmp2 = new byte[len];
                    bb.Get(tmp2);
                    objects.Add(tmp2);
                    if (s != null)
                    {
                        s.Append(GXCommon.ToHex(tmp2, false));
                    }
                    break;
                }
                break;

            case (byte)BerType.Boolean:
                bool b = bb.GetUInt8() != 0;
                objects.Add(b);
                if (s != null)
                {
                    s.Append(Convert.ToString(b));
                }
                break;

            default:
                throw new System.ArgumentException("Invalid type: " + type);
            }
            if (s != null)
            {
                s.Append("</" + tagString + ">\r\n");
            }
        }
        /// <summary>
        /// Update ephemeral keys.
        /// </summary>
        /// <param name="client">DLMS Client.</param>
        /// <param name="value">Received reply from the server.</param>
        /// <returns>List of Parsed key id and GUAK. This is for debugging purpose.</returns>
        public List <KeyValuePair <GlobalKeyType, byte[]> > UpdateEphemeralKeys(GXDLMSSecureClient client, GXByteBuffer value)
        {
            if (client == null)
            {
                throw new ArgumentNullException(nameof(client));
            }
            if (value.GetUInt8() != (byte)DataType.Array)
            {
                throw new ArgumentOutOfRangeException("Invalid tag.");
            }
            GXEcdsa c     = new GXEcdsa(client.Ciphering.EphemeralKeyPair.Key);
            int     count = GXCommon.GetObjectCount(value);
            List <KeyValuePair <GlobalKeyType, byte[]> > list = new List <KeyValuePair <GlobalKeyType, byte[]> >();

            for (int pos = 0; pos != count; ++pos)
            {
                if (value.GetUInt8() != (byte)DataType.Structure)
                {
                    throw new ArgumentOutOfRangeException("Invalid tag.");
                }
                if (value.GetUInt8() != 2)
                {
                    throw new ArgumentOutOfRangeException("Invalid length.");
                }
                if (value.GetUInt8() != (byte)DataType.Enum)
                {
                    throw new ArgumentOutOfRangeException("Invalid key id data type.");
                }
                int keyId = value.GetUInt8();
                if (keyId > 4)
                {
                    throw new ArgumentOutOfRangeException("Invalid key type.");
                }
                if (value.GetUInt8() != (byte)DataType.OctetString)
                {
                    throw new ArgumentOutOfRangeException("Invalid tag.");
                }
                if (GXCommon.GetObjectCount(value) != 128)
                {
                    throw new ArgumentOutOfRangeException("Invalid length.");
                }
                //Get ephemeral public key server.
                GXByteBuffer key = new GXByteBuffer();
                key.SetUInt8(4);
                key.Set(value, 64);
                GXPublicKey targetEphemeralKey = GXPublicKey.FromRawBytes(key.Array());
                //Get ephemeral public key signature server.
                byte[] signature = new byte[64];
                value.Get(signature);
                key.SetUInt8(0, (byte)keyId);
                //Verify signature.
                if (!GXSecure.ValidateEphemeralPublicKeySignature(key.Array(), signature, client.Ciphering.SigningKeyPair.Value))
                {
                    throw new GXDLMSCipherException("Invalid signature.");
                }
                byte[] z = c.GenerateSecret(targetEphemeralKey);
                System.Diagnostics.Debug.WriteLine("Shared secret:" + GXCommon.ToHex(z, true));
                GXByteBuffer kdf = new GXByteBuffer();
                kdf.Set(GXSecure.GenerateKDF(client.SecuritySuite, z,
                                             AlgorithmId.AesGcm128,
                                             client.Ciphering.SystemTitle,
                                             client.Settings.SourceSystemTitle, null, null));
                System.Diagnostics.Debug.WriteLine("KDF:" + kdf.ToString());
                list.Add(new KeyValuePair <GlobalKeyType, byte[]>((GlobalKeyType)keyId, kdf.SubArray(0, 16)));
            }
            //Update ephemeral keys.
            foreach (KeyValuePair <GlobalKeyType, byte[]> it in list)
            {
                switch (it.Key)
                {
                case GlobalKeyType.UnicastEncryption:
                    client.Settings.EphemeralBlockCipherKey = it.Value;
                    break;

                case GlobalKeyType.BroadcastEncryption:
                    client.Settings.EphemeralBroadcastBlockCipherKey = it.Value;
                    break;

                case GlobalKeyType.Authentication:
                    client.Settings.EphemeralAuthenticationKey = it.Value;
                    break;

                case GlobalKeyType.Kek:
                    client.Settings.EphemeralKek = it.Value;
                    break;
                }
            }
            return(list);
        }
Ejemplo n.º 13
0
        private static void HanleSetRequestWithList(GXDLMSSettings settings, byte invokeID, GXDLMSServer server, GXByteBuffer data, GXDLMSLNParameters p, GXByteBuffer replyData, GXDLMSTranslatorStructure xml)
        {
            ValueEventArgs        e;
            int                   cnt  = GXCommon.GetObjectCount(data);
            List <ValueEventArgs> list = new List <ValueEventArgs>();

            if (xml != null)
            {
                xml.AppendStartTag(TranslatorTags.AttributeDescriptorList, "Qty", xml.IntegerToHex(cnt, 2));
            }
            try
            {
                for (int pos = 0; pos != cnt; ++pos)
                {
                    ObjectType ci = (ObjectType)data.GetUInt16();
                    byte[]     ln = new byte[6];
                    data.Get(ln);
                    short attributeIndex = data.GetUInt8();
                    // AccessSelection
                    int    selection  = data.GetUInt8();
                    int    selector   = 0;
                    object parameters = null;
                    if (selection != 0)
                    {
                        selector = data.GetUInt8();
                        GXDataInfo info = new GXDataInfo();
                        parameters = GXCommon.GetData(settings, data, info);
                    }
                    if (xml != null)
                    {
                        xml.AppendStartTag(TranslatorTags.AttributeDescriptorWithSelection);
                        xml.AppendStartTag(TranslatorTags.AttributeDescriptor);
                        xml.AppendComment(ci.ToString());
                        xml.AppendLine(TranslatorTags.ClassId, "Value", xml.IntegerToHex((int)ci, 4));
                        xml.AppendComment(GXCommon.ToLogicalName(ln));
                        xml.AppendLine(TranslatorTags.InstanceId, "Value", GXCommon.ToHex(ln, false));
                        xml.AppendLine(TranslatorTags.AttributeId, "Value", xml.IntegerToHex(attributeIndex, 2));
                        xml.AppendEndTag(TranslatorTags.AttributeDescriptor);
                        xml.AppendEndTag(TranslatorTags.AttributeDescriptorWithSelection);
                    }
                    else
                    {
                        GXDLMSObject obj = settings.Objects.FindByLN(ci, GXCommon.ToLogicalName(ln));
                        if (obj == null)
                        {
                            obj = server.NotifyFindObject(ci, 0, GXCommon.ToLogicalName(ln));
                        }
                        if (obj == null)
                        {
                            // "Access Error : Device reports a undefined object."
                            e       = new ValueEventArgs(server, obj, attributeIndex, 0, 0);
                            e.Error = ErrorCode.UndefinedObject;
                            list.Add(e);
                        }
                        else
                        {
                            ValueEventArgs arg = new ValueEventArgs(server, obj, attributeIndex, selector, parameters);
                            arg.InvokeId = invokeID;
                            if (server.NotifyGetAttributeAccess(arg) == AccessMode.NoAccess)
                            {
                                //Read Write denied.
                                arg.Error = ErrorCode.ReadWriteDenied;
                                list.Add(arg);
                            }
                            else
                            {
                                list.Add(arg);
                            }
                        }
                    }
                }
                cnt = GXCommon.GetObjectCount(data);
                if (xml != null)
                {
                    xml.AppendEndTag(TranslatorTags.AttributeDescriptorList);
                    xml.AppendStartTag(TranslatorTags.ValueList, "Qty", xml.IntegerToHex(cnt, 2));
                }
                for (int pos = 0; pos != cnt; ++pos)
                {
                    GXDataInfo di = new GXDataInfo();
                    di.xml = xml;
                    if (xml != null && xml.OutputType == TranslatorOutputType.StandardXml)
                    {
                        xml.AppendStartTag(Command.WriteRequest, SingleReadResponse.Data);
                    }
                    object value = GXCommon.GetData(settings, data, di);
                    if (!di.Complete)
                    {
                        value = GXCommon.ToHex(data.Data, false, data.Position, data.Size - data.Position);
                    }
                    else if (value is byte[])
                    {
                        value = GXCommon.ToHex((byte[])value, false);
                    }
                    if (xml != null && xml
                        .OutputType == TranslatorOutputType.StandardXml)
                    {
                        xml.AppendEndTag(Command.WriteRequest, SingleReadResponse.Data);
                    }
                }
                if (xml != null)
                {
                    xml.AppendEndTag(TranslatorTags.ValueList);
                }
            }
            catch (Exception ex)
            {
                if (xml == null)
                {
                    throw ex;
                }
            }
        }
Ejemplo n.º 14
0
        /// <summary>
        /// Handle get request with list command.
        /// </summary>
        /// <param name="data">Received data.</param>
        private static void GetRequestWithList(GXDLMSSettings settings, byte invokeID, GXDLMSServer server, GXByteBuffer data, GXByteBuffer replyData, GXDLMSTranslatorStructure xml)
        {
            ValueEventArgs e;
            GXByteBuffer   bb = new GXByteBuffer();
            int            pos;
            int            cnt = GXCommon.GetObjectCount(data);

            GXCommon.SetObjectCount(cnt, bb);
            List <ValueEventArgs> list = new List <ValueEventArgs>();

            if (xml != null)
            {
                xml.AppendStartTag(TranslatorTags.AttributeDescriptorList, "Qty", xml.IntegerToHex(cnt, 2));
            }
            try
            {
                for (pos = 0; pos != cnt; ++pos)
                {
                    ObjectType ci = (ObjectType)data.GetUInt16();
                    byte[]     ln = new byte[6];
                    data.Get(ln);
                    short attributeIndex = data.GetUInt8();
                    // AccessSelection
                    int    selection  = data.GetUInt8();
                    int    selector   = 0;
                    object parameters = null;
                    if (selection != 0)
                    {
                        selector = data.GetUInt8();
                        GXDataInfo info = new GXDataInfo();
                        parameters = GXCommon.GetData(settings, data, info);
                    }
                    if (xml != null)
                    {
                        xml.AppendStartTag(TranslatorTags.AttributeDescriptorWithSelection);
                        xml.AppendStartTag(TranslatorTags.AttributeDescriptor);
                        xml.AppendComment(ci.ToString());
                        xml.AppendLine(TranslatorTags.ClassId, "Value", xml.IntegerToHex((int)ci, 4));
                        xml.AppendComment(GXCommon.ToLogicalName(ln));
                        xml.AppendLine(TranslatorTags.InstanceId, "Value", GXCommon.ToHex(ln, false));
                        xml.AppendLine(TranslatorTags.AttributeId, "Value", xml.IntegerToHex(attributeIndex, 2));
                        xml.AppendEndTag(TranslatorTags.AttributeDescriptor);
                        xml.AppendEndTag(TranslatorTags.AttributeDescriptorWithSelection);
                    }
                    else
                    {
                        GXDLMSObject obj = settings.Objects.FindByLN(ci, GXCommon.ToLogicalName(ln));
                        if (obj == null)
                        {
                            obj = server.NotifyFindObject(ci, 0, GXCommon.ToLogicalName(ln));
                        }
                        if (obj == null)
                        {
                            // "Access Error : Device reports a undefined object."
                            e       = new ValueEventArgs(server, obj, attributeIndex, 0, 0);
                            e.Error = ErrorCode.UndefinedObject;
                            list.Add(e);
                        }
                        else
                        {
                            ValueEventArgs arg = new ValueEventArgs(server, obj, attributeIndex, selector, parameters);
                            arg.InvokeId = invokeID;
                            if (server.NotifyGetAttributeAccess(arg) == AccessMode.NoAccess)
                            {
                                //Read Write denied.
                                arg.Error = ErrorCode.ReadWriteDenied;
                                list.Add(arg);
                            }
                            else
                            {
                                list.Add(arg);
                            }
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                if (xml == null)
                {
                    throw ex;
                }
            }
            if (xml != null)
            {
                xml.AppendEndTag(TranslatorTags.AttributeDescriptorList);
                return;
            }

            server.NotifyRead(list.ToArray());
            object value;

            pos = 0;
            foreach (ValueEventArgs it in list)
            {
                try
                {
                    if (it.Handled)
                    {
                        value = it.Value;
                    }
                    else
                    {
                        value = (it.Target as IGXDLMSBase).GetValue(settings, it);
                    }
                    bb.SetUInt8(it.Error);
                    if (it.ByteArray)
                    {
                        bb.Set((byte[])value);
                    }
                    else
                    {
                        GXDLMS.AppendData(settings, it.Target, it.Index, bb, value);
                    }
                    invokeID = (byte)it.InvokeId;
                }
                catch (Exception)
                {
                    bb.SetUInt8((byte)ErrorCode.HardwareFault);
                }
                if (settings.Index != settings.Count)
                {
                    server.transaction = new GXDLMSLongTransaction(list.ToArray(), Command.GetRequest, null);
                }
                ++pos;
            }
            server.NotifyPostRead(list.ToArray());
            GXDLMSLNParameters p = new GXDLMSLNParameters(null, settings, invokeID, Command.GetResponse, 3, null, bb, 0xFF);

            GXDLMS.GetLNPdu(p, replyData);
        }
Ejemplo n.º 15
0
        /// <summary>
        /// Decrypt data.
        /// </summary>
        /// <param name="p">Decryption parameters</param>
        /// <returns>Decrypted data.</returns>
        public static byte[] DecryptAesGcm(AesGcmParameter p, GXByteBuffer data)
        {
            if (data == null || data.Size < 2)
            {
                throw new ArgumentOutOfRangeException("cryptedData");
            }
            byte[]  tmp;
            int     len;
            Command cmd = (Command)data.GetUInt8();

            switch (cmd)
            {
            case Command.GeneralGloCiphering:
            case Command.GeneralDedCiphering:
                len = GXCommon.GetObjectCount(data);
                if (len != 0)
                {
                    p.SystemTitle = new byte[len];
                    data.Get(p.SystemTitle);
                    if (p.Xml != null && p.Xml.Comments)
                    {
                        p.Xml.AppendComment(GXCommon.SystemTitleToString(Standard.DLMS, p.SystemTitle, true));
                    }
                }
                if (p.SystemTitle == null || p.SystemTitle.Length != 8)
                {
                    if (p.Xml == null)
                    {
                        throw new ArgumentNullException("Invalid sender system title.");
                    }
                    else
                    {
                        p.Xml.AppendComment("Invalid sender system title.");
                    }
                }
                break;

            case Command.GeneralCiphering:
            case Command.GloInitiateRequest:
            case Command.GloInitiateResponse:
            case Command.GloReadRequest:
            case Command.GloReadResponse:
            case Command.GloWriteRequest:
            case Command.GloWriteResponse:
            case Command.GloGetRequest:
            case Command.GloGetResponse:
            case Command.GloSetRequest:
            case Command.GloSetResponse:
            case Command.GloMethodRequest:
            case Command.GloMethodResponse:
            case Command.GloEventNotification:
            case Command.DedInitiateRequest:
            case Command.DedInitiateResponse:
            case Command.DedGetRequest:
            case Command.DedGetResponse:
            case Command.DedSetRequest:
            case Command.DedSetResponse:
            case Command.DedMethodRequest:
            case Command.DedMethodResponse:
            case Command.DedEventNotification:
            case Command.DedReadRequest:
            case Command.DedReadResponse:
            case Command.DedWriteRequest:
            case Command.DedWriteResponse:
            case Command.GloConfirmedServiceError:
            case Command.DedConfirmedServiceError:
                break;

            default:
                throw new ArgumentOutOfRangeException("cryptedData");
            }
            int          value         = 0;
            GXPrivateKey key           = null;
            GXPublicKey  pub           = null;
            GXByteBuffer transactionId = null;

            if (cmd == Command.GeneralCiphering)
            {
                transactionId = new GXByteBuffer();
                len           = GXCommon.GetObjectCount(data);
                GXCommon.SetObjectCount(len, transactionId);
                transactionId.Set(data, len);
                p.TransactionId = transactionId.GetUInt64(1);
                len             = GXCommon.GetObjectCount(data);
                if (len != 0)
                {
                    tmp = new byte[len];
                    data.Get(tmp);
                    p.SystemTitle = tmp;
                }
                if (p.SystemTitle == null || p.SystemTitle.Length != 8)
                {
                    if (p.Xml == null)
                    {
                        throw new ArgumentNullException("Invalid sender system title.");
                    }
                    else
                    {
                        p.Xml.AppendComment("Invalid sender system title.");
                    }
                }
                len = GXCommon.GetObjectCount(data);
                tmp = new byte[len];
                data.Get(tmp);
                p.RecipientSystemTitle = tmp;
                // Get date time.
                len = GXCommon.GetObjectCount(data);
                if (len != 0)
                {
                    tmp = new byte[len];
                    data.Get(tmp);
                    p.DateTime = tmp;
                }
                // other-information
                len = data.GetUInt8();
                if (len != 0)
                {
                    tmp = new byte[len];
                    data.Get(tmp);
                    p.OtherInformation = tmp;
                }
                // KeyInfo OPTIONAL
                len = data.GetUInt8();
                // AgreedKey CHOICE tag.
                data.GetUInt8();
                // key-parameters
                len             = data.GetUInt8();
                value           = data.GetUInt8();
                p.KeyParameters = value;
                if (value == (int)KeyAgreementScheme.OnePassDiffieHellman)
                {
                    // key-ciphered-data
                    len = GXCommon.GetObjectCount(data);
                    GXByteBuffer bb = new GXByteBuffer();
                    bb.Set(data, len);
                    if (p.Xml != null)
                    {
                        p.KeyCipheredData = bb.Array();
                        //Find key agreement key using subject.
                        string subject = GXAsn1Converter.SystemTitleToSubject(p.SystemTitle);
                        foreach (KeyValuePair <GXPkcs8, GXx509Certificate> it in p.Settings.Keys)
                        {
                            if (it.Key != null && it.Value.KeyUsage == ASN.Enums.KeyUsage.KeyAgreement && it.Value.Subject.Contains(subject))
                            {
                                key = it.Key.PrivateKey;
                                //Get recipient Ephemeral public key.
                                subject = GXAsn1Converter.SystemTitleToSubject(p.RecipientSystemTitle);
                                foreach (KeyValuePair <GXPkcs8, GXx509Certificate> it2 in p.Settings.Keys)
                                {
                                    if (it2.Value != null && it2.Value.KeyUsage == ASN.Enums.KeyUsage.KeyAgreement && it2.Value.Subject.Contains(subject))
                                    {
                                        pub = it2.Value.PublicKey;
                                        break;
                                    }
                                }
                                break;
                            }
                        }
                        if (key == null)
                        {
                            //Find key agreement key using subject.
                            subject = GXAsn1Converter.SystemTitleToSubject(p.RecipientSystemTitle);
                            foreach (KeyValuePair <GXPkcs8, GXx509Certificate> it in p.Settings.Keys)
                            {
                                if (it.Key != null && it.Value.KeyUsage == ASN.Enums.KeyUsage.KeyAgreement && it.Value.Subject.Contains(subject))
                                {
                                    key = it.Key.PrivateKey;
                                    break;
                                }
                            }
                        }
                    }
                    else
                    {
                        key = p.Settings.Cipher.KeyAgreementKeyPair.Key;
                    }
                    if (key != null && pub == null)
                    {
                        //Get Ephemeral public key.
                        int keySize = len / 2;
                        pub = GXPublicKey.FromRawBytes(bb.SubArray(0, keySize));
                    }
                }
                else if (value == (int)KeyAgreementScheme.StaticUnifiedModel)
                {
                    len = GXCommon.GetObjectCount(data);
                    if (len != 0)
                    {
                        throw new ArgumentException("Invalid key parameters");
                    }
                    if (p.Xml != null)
                    {
                        //Find key agreement key using subject.
                        string subject = GXAsn1Converter.SystemTitleToSubject(p.RecipientSystemTitle);
                        foreach (KeyValuePair <GXPkcs8, GXx509Certificate> it in p.Settings.Keys)
                        {
                            if (it.Value.KeyUsage == ASN.Enums.KeyUsage.KeyAgreement && it.Value.Subject.Contains(subject))
                            {
                                key = it.Key.PrivateKey;
                                break;
                            }
                        }
                        if (key != null)
                        {
                            //Find key agreement key using subject.
                            subject = GXAsn1Converter.SystemTitleToSubject(p.Settings.SourceSystemTitle);
                            foreach (KeyValuePair <GXPkcs8, GXx509Certificate> it in p.Settings.Keys)
                            {
                                if (it.Value.KeyUsage == ASN.Enums.KeyUsage.KeyAgreement && it.Value.Subject.Contains(subject))
                                {
                                    pub = it.Value.PublicKey;
                                    break;
                                }
                            }
                        }
                    }
                    else
                    {
                        key = p.Settings.Cipher.KeyAgreementKeyPair.Key;
                        pub = p.Settings.Cipher.KeyAgreementKeyPair.Value;
                    }
                }
                else
                {
                    throw new ArgumentException("key-parameters");
                }
            }
            len = GXCommon.GetObjectCount(data);
            if (len > data.Available)
            {
                throw new Exception("Not enought data.");
            }
            p.CipheredContent = data.Remaining();
            byte sc = data.GetUInt8();

            p.SecuritySuite = (SecuritySuite)(sc & 0x3);
            p.Security      = (Security)(sc & 0x30);
            if ((sc & 0x80) != 0)
            {
                System.Diagnostics.Debug.WriteLine("Compression is used.");
            }
            if ((sc & 0x40) != 0)
            {
                System.Diagnostics.Debug.WriteLine("Error: Key_Set is used.");
            }
            if ((sc & 0x20) != 0)
            {
                System.Diagnostics.Debug.WriteLine("Encryption is applied.");
            }
            if (key != null)
            {
                if (value == (int)KeyAgreementScheme.OnePassDiffieHellman)
                {
                    GXEcdsa c = new GXEcdsa(key);
                    //Get Ephemeral signing key and verify it.
                    byte[] z = c.GenerateSecret(pub);
                    System.Diagnostics.Debug.WriteLine("Originator ephemeral public key: " + pub.ToHex());
                    System.Diagnostics.Debug.WriteLine("Recipient private agreement key: " + key.ToHex());
                    System.Diagnostics.Debug.WriteLine("Shared secret:" + GXCommon.ToHex(z, true));

                    GXByteBuffer kdf = new GXByteBuffer();
                    kdf.Set(GXSecure.GenerateKDF(p.SecuritySuite, z,
                                                 p.SecuritySuite == SecuritySuite.Ecdsa256 ? AlgorithmId.AesGcm128 : AlgorithmId.AesGcm256,
                                                 p.SystemTitle,
                                                 p.RecipientSystemTitle,
                                                 null, null));
                    System.Diagnostics.Debug.WriteLine("KDF:" + kdf.ToString());
                    p.BlockCipherKey = kdf.SubArray(0, 16);
                }
                else if (value == (int)KeyAgreementScheme.StaticUnifiedModel)
                {
                    GXEcdsa c = new GXEcdsa(key);
                    byte[]  z = c.GenerateSecret(pub);
                    System.Diagnostics.Debug.WriteLine("Shared secret:" + GXCommon.ToHex(z, true));
                    GXByteBuffer kdf = new GXByteBuffer();
                    kdf.Set(GXSecure.GenerateKDF(p.SecuritySuite, z,
                                                 p.SecuritySuite == SecuritySuite.Ecdsa256 ? AlgorithmId.AesGcm128 : AlgorithmId.AesGcm256,
                                                 p.SystemTitle,
                                                 transactionId.Array(),
                                                 p.RecipientSystemTitle,
                                                 null));
                    System.Diagnostics.Debug.WriteLine("KDF:" + kdf.ToString());
                    p.BlockCipherKey = kdf.SubArray(0, 16);
                }
                else
                {
                    throw new ArgumentOutOfRangeException("Invalid Key-id value.");
                }
            }
            UInt32 invocationCounter = data.GetUInt32();

            p.InvocationCounter = invocationCounter;
            System.Diagnostics.Debug.WriteLine("Decrypt settings: " + p.ToString());
            System.Diagnostics.Debug.WriteLine("Encrypted: " + GXCommon.ToHex(data.Data,
                                                                              false, data.Position, data.Size - data.Position));
            byte[] tag = new byte[12];
            byte[] encryptedData;
            int    length;

            if (p.Security == Security.Authentication)
            {
                length        = data.Size - data.Position - 12;
                encryptedData = new byte[length];
                data.Get(encryptedData);
                data.Get(tag);
                // Check tag.
                EncryptAesGcm(p, encryptedData);
                if (!GXDLMSChipperingStream.TagsEquals(tag, p.CountTag))
                {
                    if (p.Xml == null)
                    {
                        throw new GXDLMSException("Decrypt failed. Invalid tag.");
                    }
                    else
                    {
                        p.Xml.AppendComment("Decrypt failed. Invalid tag.");
                    }
                }
                return(encryptedData);
            }
            byte[] ciphertext = null;
            if (p.Security == Security.Encryption)
            {
                length     = data.Size - data.Position;
                ciphertext = new byte[length];
                data.Get(ciphertext);
            }
            else if (p.Security == Security.AuthenticationEncryption)
            {
                length     = data.Size - data.Position - 12;
                ciphertext = new byte[length];
                data.Get(ciphertext);
                data.Get(tag);
            }
            byte[] aad = GetAuthenticatedData(p, ciphertext),
            iv = GetNonse(invocationCounter, p.SystemTitle);
            GXDLMSChipperingStream gcm = new GXDLMSChipperingStream(p.Security, true,
                                                                    p.BlockCipherKey, aad, iv, tag);

            gcm.Write(ciphertext);
            byte[] decrypted = gcm.FlushFinalBlock();
            System.Diagnostics.Debug.WriteLine("Decrypted: " + GXCommon.ToHex(decrypted, true));
            if (p.Security != Security.Encryption)
            {
                if (!GXCommon.Compare(gcm.GetTag(), tag))
                {
                    if (p.Xml == null)
                    {
                        throw new Exception("Decrypt failed. Invalid authentication tag.");
                    }
                    p.Xml.AppendComment("Decrypt failed. Invalid authentication tag.");
                }
            }
            return(decrypted);
        }
Ejemplo n.º 16
0
        /// <summary>
        /// Decrypt data.
        /// </summary>
        /// <param name="p">Decryption parameters</param>
        /// <returns>Decrypted data.</returns>
        public static byte[] DecryptAesGcm(AesGcmParameter p, GXByteBuffer data)
        {
            if (data == null || data.Size < 2)
            {
                throw new ArgumentOutOfRangeException("cryptedData");
            }
            int     len;
            Command cmd = (Command)data.GetUInt8();

            switch (cmd)
            {
            case Command.GeneralGloCiphering:
                len = GXCommon.GetObjectCount(data);
                if (len != 0)
                {
                    p.SystemTitle = new byte[len];
                    data.Get(p.SystemTitle);
                }
                break;

            case Command.GloInitiateRequest:
            case Command.GloInitiateResponse:
            case Command.GloReadRequest:
            case Command.GloReadResponse:
            case Command.GloWriteRequest:
            case Command.GloWriteResponse:
            case Command.GloGetRequest:
            case Command.GloGetResponse:
            case Command.GloSetRequest:
            case Command.GloSetResponse:
            case Command.GloMethodRequest:
            case Command.GloMethodResponse:
            case Command.GloEventNotificationRequest:
                break;

            default:
                throw new ArgumentOutOfRangeException("cryptedData");
            }
            len                 = Gurux.DLMS.Internal.GXCommon.GetObjectCount(data);
            p.Security          = (Gurux.DLMS.Enums.Security)data.GetUInt8();
            p.InvocationCounter = data.GetUInt32();
            System.Diagnostics.Debug.WriteLine("Decrypt settings: " + p.ToString());
            System.Diagnostics.Debug.WriteLine("Encrypted: " + GXCommon.ToHex(data.Array(), true));

            byte[] tag = new byte[12];
            byte[] encryptedData;
            int    length;

            if (p.Security == Gurux.DLMS.Enums.Security.Authentication)
            {
                length        = data.Size - data.Position - 12;
                encryptedData = new byte[length];
                data.Get(encryptedData);
                data.Get(tag);
                // Check tag.
                EncryptAesGcm(p, encryptedData);
                if (!GXDLMSChipperingStream.TagsEquals(tag, p.CountTag))
                {
                    throw new GXDLMSException("Decrypt failed. Invalid tag.");
                }
                return(encryptedData);
            }
            byte[] ciphertext = null;
            if (p.Security == Gurux.DLMS.Enums.Security.Encryption)
            {
                length     = data.Size - data.Position;
                ciphertext = new byte[length];
                data.Get(ciphertext);
            }
            else if (p.Security == Gurux.DLMS.Enums.Security.AuthenticationEncryption)
            {
                length     = data.Size - data.Position - 12;
                ciphertext = new byte[length];
                data.Get(ciphertext);
                data.Get(tag);
            }
            byte[] aad = GetAuthenticatedData(p.Security, p.AuthenticationKey, ciphertext);
            byte[] iv  = GetNonse(p.InvocationCounter, p.SystemTitle);
            GXDLMSChipperingStream gcm = new GXDLMSChipperingStream(p.Security, true, p.BlockCipherKey, aad, iv, tag);

            gcm.Write(ciphertext);
            ciphertext = gcm.FlushFinalBlock();
            if (p.Security == Gurux.DLMS.Enums.Security.AuthenticationEncryption)
            {
                // Check tag.
                EncryptAesGcm(p, ciphertext);
                if (!GXDLMSChipperingStream.TagsEquals(tag, p.CountTag))
                {
                    //    throw new GXDLMSException("Decrypt failed. Invalid tag.");
                }
            }
            return(ciphertext);
        }
Ejemplo n.º 17
0
        ///
        ///<summary>Handle read request.
        /// </summary>
        ///<returns> Reply to the client. </returns>
        ///
        private byte[][] HandleReadRequest()
        {
            GXByteBuffer data = Reply.Data;
            short        type;
            object       value = null;
            GXByteBuffer bb    = new GXByteBuffer();
            int          cnt   = GXCommon.GetObjectCount(data);

            GXCommon.SetObjectCount(cnt, bb);
            GXSNInfo info;

            for (int pos = 0; pos != cnt; ++pos)
            {
                type = data.GetUInt8();
                // GetRequest normal
                if (type == 2)
                {
                    int sn = data.GetUInt16();
                    info = FindSNObject(sn);
                    if (!info.IsAction)
                    {
                        ValueEventArgs e = new ValueEventArgs(info.Item, info.Index, 0, null);
                        Read(e);
                        if (e.Handled)
                        {
                            value = e.Value;
                        }
                        else
                        {
                            value = (info.Item as IGXDLMSBase).GetValue(Settings, info.Index, 0, null);
                        }
                        // Set status.
                        bb.SetUInt8(0);
                        GXDLMS.AppedData(info.Item, info.Index, bb, value);
                    }
                    else
                    {
                        ValueEventArgs e = new ValueEventArgs(info.Item, info.Index, 0, null);
                        Action(e);
                        if (e.Handled)
                        {
                            value = e.Value;
                        }
                        else
                        {
                            value = ((IGXDLMSBase)info.Item).Invoke(Settings, info.Index, null);
                        }
                        // Set status.
                        bb.SetUInt8(0);
                        // Add value
                        bb.SetUInt8(GXCommon.GetValueType(value));
                        bb.Add(value);
                    }
                }
                else if (type == 2)
                {
                    // Get request for next data block
                    throw new System.ArgumentException("TODO: Invalid Command.");
                }
                else if (type == 4)
                {
                    // Parameterised access.
                    int        sn         = data.GetUInt16();
                    int        selector   = data.GetUInt8();
                    GXDataInfo di         = new GXDataInfo();
                    object     parameters = GXCommon.GetData(data, di);
                    info = FindSNObject(sn);
                    if (!info.IsAction)
                    {
                        ValueEventArgs e = new ValueEventArgs(info.Item, info.Index, 0, parameters);
                        Read(e);
                        if (e.Handled)
                        {
                            value = e.Value;
                        }
                        else
                        {
                            value = (info.Item as IGXDLMSBase).GetValue(Settings, info.Index, selector, parameters);
                        }
                        // Set status.
                        bb.SetUInt8(0);
                        GXDLMS.AppedData(info.Item, info.Index, bb, value);
                    }
                    else
                    {
                        ValueEventArgs e = new ValueEventArgs(info.Item, info.Index, 0, parameters);
                        e.Value = parameters;
                        Action(e);
                        if (e.Handled)
                        {
                            value = e.Value;
                        }
                        else
                        {
                            value = ((IGXDLMSBase)info.Item).Invoke(Settings, info.Index, parameters);
                        }
                        // Add value
                        bb.Add(value);
                    }
                }
                else
                {
                    throw new System.ArgumentException("Invalid Command.");
                }
            }
            return(GXDLMS.SplitPdu(Settings, Command.ReadResponse, 1, bb,
                                   ErrorCode.Ok, DateTime.MinValue)[0]);
        }
Ejemplo n.º 18
0
        private byte[][] HandleGetRequest()
        {
            ErrorCode    error = ErrorCode.Ok;
            GXByteBuffer data  = Reply.Data;
            GXByteBuffer bb    = new GXByteBuffer();
            short        type;
            int          index      = 0;
            object       parameters = null;

            // Get type.
            type = data.GetUInt8();
            // Get invoke ID and priority.
            data.GetUInt8();
            // GetRequest normal
            if (type == 1)
            {
                Settings.ResetBlockIndex();
                ServerReply.Index = 0;
                parameters        = null;
                // CI
                ObjectType ci = (ObjectType)data.GetUInt16();
                byte[]     ln = new byte[6];
                data.Get(ln);
                // Attribute Id
                int          attributeIndex = data.GetUInt8();
                GXDLMSObject obj            = Settings.Objects.FindByLN(ci, GXDLMSObject.ToLogicalName(ln));
                if (obj == null)
                {
                    obj = FindObject(ci, 0, GXDLMSObject.ToLogicalName(ln));
                }
                if (obj == null)
                {
                    // "Access Error : Device reports a undefined object."
                    error = ErrorCode.UndefinedObject;
                }
                else
                {
                    // AccessSelection
                    int selection = data.GetUInt8();
                    int selector  = 0;
                    if (selection != 0)
                    {
                        selector = data.GetUInt8();
                        GXDataInfo info = new GXDataInfo();
                        parameters = GXCommon.GetData(data, info);
                    }

                    ValueEventArgs e = new ValueEventArgs(obj, attributeIndex, 0, parameters);
                    Read(e);
                    object value;
                    if (e.Handled)
                    {
                        value = e.Value;
                    }
                    else
                    {
                        value = (obj as IGXDLMSBase).GetValue(Settings, attributeIndex, selector, parameters);
                    }
                    GXDLMS.AppedData(obj, attributeIndex, bb, value);
                }
                ServerReply.ReplyMessages = GXDLMS.SplitPdu(Settings, Command.GetResponse, 1, bb, error, DateTime.MinValue);
            }
            else if (type == 2)
            {
                // Get request for next data block
                // Get block index.
                index = (int)data.GetUInt32();
                if (index != Settings.BlockIndex + 1)
                {
                    Debug.WriteLine("handleGetRequest failed. Invalid block number. " + Settings.BlockIndex + "/" + index);
                    ServerReply.ReplyMessages = GXDLMS.SplitPdu(Settings, Command.GetResponse, 1, bb,
                                                                ErrorCode.DataBlockNumberInvalid, DateTime.MinValue);
                    index             = 0;
                    ServerReply.Index = index;
                }
                else
                {
                    Settings.IncreaseBlockIndex();
                    index             = ServerReply.Index + 1;
                    ServerReply.Index = index;
                }
            }
            else if (type == 3)
            {
                // Get request with a list.
                int cnt = GXCommon.GetObjectCount(data);
                GXCommon.SetObjectCount(cnt, bb);
                for (int pos = 0; pos != cnt; ++pos)
                {
                    ObjectType ci = (ObjectType)data.GetUInt16();
                    byte[]     ln = new byte[6];
                    data.Get(ln);
                    short attributeIndex = data.GetUInt8();

                    GXDLMSObject obj = Settings.Objects.FindByLN(ci, GXDLMSObject.ToLogicalName(ln));
                    if (obj == null)
                    {
                        obj = FindObject(ci, 0, GXDLMSObject.ToLogicalName(ln));
                    }
                    if (obj == null)
                    {
                        // "Access Error : Device reports a undefined object."
                        error = ErrorCode.UndefinedObject;
                    }
                    else
                    {
                        // AccessSelection
                        int selection = data.GetUInt8();
                        int selector  = 0;
                        if (selection != 0)
                        {
                            selector = data.GetUInt8();
                            GXDataInfo info = new GXDataInfo();
                            parameters = GXCommon.GetData(data, info);
                        }
                        try
                        {
                            ValueEventArgs e = new ValueEventArgs(obj, attributeIndex, 0, parameters);
                            Read(e);
                            object value;
                            if (e.Handled)
                            {
                                value = e.Value;
                            }
                            else
                            {
                                value = (obj as IGXDLMSBase).GetValue(Settings, attributeIndex, selector, parameters);
                            }
                            bb.SetUInt8(ErrorCode.Ok);
                            GXDLMS.AppedData(obj, attributeIndex, bb, value);
                        }
                        catch (Exception)
                        {
                            bb.SetUInt8(1);
                            bb.SetUInt8(ErrorCode.HardwareFault);
                        }
                    }
                }
                ServerReply.ReplyMessages = GXDLMS.SplitPdu(Settings, Command.GetResponse, 3, bb, error, DateTime.MinValue);
            }
            else
            {
                Debug.WriteLine("handleGetRequest failed. Invalid command type.");
                Settings.ResetBlockIndex();
                // Access Error : Device reports a hardware fault.
                ServerReply.ReplyMessages = GXDLMS.SplitPdu(Settings, Command.GetResponse, 1, bb, ErrorCode.HardwareFault, DateTime.MinValue);
            }
            ServerReply.Index = index;
            return(ServerReply.ReplyMessages[index]);
        }
Ejemplo n.º 19
0
        ///<summary>
        /// Handle write request.
        ///</summary>
        ///<param name="Reply">
        /// Received data from the client.
        /// </param>
        ///<returns>
        /// Reply.
        ///</returns>
        private byte[][] HandleWriteRequest()
        {
            GXByteBuffer data = Reply.Data;
            short        type;
            object       value;
            // Get object count.
            IList <GXSNInfo> targets = new List <GXSNInfo>();
            int          cnt         = GXCommon.GetObjectCount(data);
            GXByteBuffer results     = new GXByteBuffer((ushort)cnt);

            for (int pos = 0; pos != cnt; ++pos)
            {
                type = data.GetUInt8();
                if (type == 2)
                {
                    int      sn   = data.GetUInt16();
                    GXSNInfo info = FindSNObject(sn);
                    targets.Add(info);
                    // If target is unknown.
                    if (info == null)
                    {
                        // Device reports a undefined object.
                        results.SetUInt8(ErrorCode.UndefinedObject);
                    }
                    else
                    {
                        results.SetUInt8(ErrorCode.Ok);
                    }
                }
                else
                {
                    // Device reports a HW error.
                    results.SetUInt8(ErrorCode.HardwareFault);
                }
            }
            // Get data count.
            cnt = GXCommon.GetObjectCount(data);
            GXDataInfo di = new GXDataInfo();

            for (int pos = 0; pos != cnt; ++pos)
            {
                if (results.GetUInt8(pos) == 0)
                {
                    // If object has found.
                    GXSNInfo target = targets[pos];
                    value = GXCommon.GetData(data, di);
                    if (value is byte[])
                    {
                        DataType dt = target.Item.GetDataType(target.Index);
                        if (dt != DataType.None && dt != DataType.OctetString)
                        {
                            value = GXDLMSClient.ChangeType((byte[])value, dt);
                        }
                    }
                    di.Clear();
                    AccessMode am = target.Item.GetAccess(target.Index);
                    // If write is denied.
                    if (am != AccessMode.Write && am != AccessMode.ReadWrite)
                    {
                        results.SetUInt8((byte)pos, (byte)ErrorCode.ReadWriteDenied);
                    }
                    else
                    {
                        ValueEventArgs e = new ValueEventArgs(target.Item, target.Index, 0, null);
                        e.Value = value;
                        Write(e);
                        if (!e.Handled)
                        {
                            (target.Item as IGXDLMSBase).SetValue(Settings, target.Index, value);
                        }
                    }
                }
            }
            GXByteBuffer bb = new GXByteBuffer((UInt16)(2 * cnt + 2));

            GXCommon.SetObjectCount(cnt, bb);
            byte ret;

            for (int pos = 0; pos != cnt; ++pos)
            {
                ret = results.GetUInt8(pos);
                // If meter returns error.
                if (ret != 0)
                {
                    bb.SetUInt8(1);
                }
                bb.SetUInt8(ret);
            }
            return(GXDLMS.SplitPdu(Settings, Command.WriteResponse, 1, bb, ErrorCode.Ok, DateTime.MinValue)[0]);
        }
Ejemplo n.º 20
0
        private static void HandleSetRequestNormal(GXDLMSSettings settings, GXDLMSServer server, GXByteBuffer data, byte type, GXDLMSLNParameters p, GXByteBuffer replyData, GXDLMSTranslatorStructure xml)
        {
            object     value = null;
            GXDataInfo reply = new GXDataInfo();
            // CI
            ObjectType ci = (ObjectType)data.GetUInt16();

            byte[] ln = new byte[6];
            data.Get(ln);
            // Attribute index.
            byte index = data.GetUInt8();

            // Get Access Selection.
            data.GetUInt8();
            if (type == 2)
            {
                byte lastBlock = data.GetUInt8();
                p.multipleBlocks = lastBlock == 0;
                UInt32 blockNumber = data.GetUInt32();
                if (blockNumber != settings.BlockIndex)
                {
                    Debug.WriteLine("HandleSetRequest failed. Invalid block number. " + settings.BlockIndex + "/" + blockNumber);
                    p.status = (byte)ErrorCode.DataBlockNumberInvalid;
                    return;
                }
                settings.IncreaseBlockIndex();
                int size     = GXCommon.GetObjectCount(data);
                int realSize = data.Size - data.Position;
                if (size != realSize)
                {
                    Debug.WriteLine("HandleSetRequest failed. Invalid block size.");
                    p.status = (byte)ErrorCode.DataBlockUnavailable;
                    return;
                }
                if (xml != null)
                {
                    AppendAttributeDescriptor(xml, (int)ci, ln, index);
                    xml.AppendStartTag(TranslatorTags.DataBlock);
                    xml.AppendLine(TranslatorTags.LastBlock, "Value", xml.IntegerToHex(lastBlock, 2));
                    xml.AppendLine(TranslatorTags.BlockNumber, "Value", xml.IntegerToHex(blockNumber, 8));
                    xml.AppendLine(TranslatorTags.RawData, "Value", data.RemainingHexString(false));
                    xml.AppendEndTag(TranslatorTags.DataBlock);
                }
                return;
            }
            if (xml != null)
            {
                AppendAttributeDescriptor(xml, (int)ci, ln, index);
                xml.AppendStartTag(TranslatorTags.Value);
                GXDataInfo di = new GXDataInfo();
                di.xml = xml;
                value  = GXCommon.GetData(settings, data, di);
                if (!di.Complete)
                {
                    value = GXCommon.ToHex(data.Data, false, data.Position, data.Size - data.Position);
                }
                else if (value is byte[])
                {
                    value = GXCommon.ToHex((byte[])value, false);
                }
                xml.AppendEndTag(TranslatorTags.Value);
                return;
            }

            if (!p.multipleBlocks)
            {
                settings.ResetBlockIndex();
                value = GXCommon.GetData(settings, data, reply);
            }

            GXDLMSObject obj = settings.Objects.FindByLN(ci, GXCommon.ToLogicalName(ln));

            if (obj == null)
            {
                obj = server.NotifyFindObject(ci, 0, GXCommon.ToLogicalName(ln));
            }
            // If target is unknown.
            if (obj == null)
            {
                // Device reports a undefined object.
                p.status = (byte)ErrorCode.UndefinedObject;
            }
            else
            {
                ValueEventArgs e = new ValueEventArgs(server, obj, index, 0, null);
                e.InvokeId = p.InvokeId;
                AccessMode am = server.NotifyGetAttributeAccess(e);
                // If write is denied.
                if (am != AccessMode.Write && am != AccessMode.ReadWrite)
                {
                    //Read Write denied.
                    p.status = (byte)ErrorCode.ReadWriteDenied;
                }
                else
                {
                    try
                    {
                        if (value is byte[])
                        {
                            DataType dt = (obj as IGXDLMSBase).GetDataType(index);
                            if (dt != DataType.None && dt != DataType.OctetString && dt != DataType.Structure)
                            {
                                value = GXDLMSClient.ChangeType((byte[])value, dt, settings.UseUtc2NormalTime);
                            }
                        }
                        e.Value = value;
                        ValueEventArgs[] list = new ValueEventArgs[] { e };
                        if (p.multipleBlocks)
                        {
                            server.transaction = new GXDLMSLongTransaction(list, Command.GetRequest, data);
                        }
                        server.NotifyWrite(list);
                        if (e.Error != 0)
                        {
                            p.status = (byte)e.Error;
                        }
                        else if (!e.Handled && !p.multipleBlocks)
                        {
                            (obj as IGXDLMSBase).SetValue(settings, e);
                            server.NotifyPostWrite(list);
                            if (e.Error != 0)
                            {
                                p.status = (byte)e.Error;
                            }
                        }
                        p.InvokeId = e.InvokeId;
                    }
                    catch (Exception)
                    {
                        p.status = (byte)ErrorCode.HardwareFault;
                    }
                }
            }
        }
Ejemplo n.º 21
0
 /// <summary>
 /// Get object count. If first byte is 0x80 or higger it will tell bytes count.
 /// </summary>
 /// <param name="data">Received data.</param>
 /// <returns>Object count.</returns>
 public static int GetObjectCount(GXByteBuffer data)
 {
     return(GXCommon.GetObjectCount(data));
 }
Ejemplo n.º 22
0
        ///<summary>
        /// Handle Access request.
        ///</summary>
        public static void HandleAccessRequest(GXDLMSSettings settings, GXDLMSServer server, GXByteBuffer data,
                                               GXByteBuffer reply, GXDLMSTranslatorStructure xml)
        {
            //Return error if connection is not established.
            if (xml == null && settings.Connected == ConnectionState.None && !settings.CanAccess())
            {
                reply.Set(GXDLMSServer.GenerateConfirmedServiceError(ConfirmedServiceError.InitiateError,
                                                                     ServiceError.Service, (byte)Service.Unsupported));
                return;
            }
            //Get long invoke id and priority.
            UInt32 invokeId = data.GetUInt32();

            settings.longInvokeID = invokeId;
            int len = GXCommon.GetObjectCount(data);

            byte[] tmp = null;
            // If date time is given.
            if (len != 0)
            {
                tmp = new byte[len];
                data.Get(tmp);
                if (xml == null)
                {
                    DataType dt = DataType.DateTime;
                    if (len == 4)
                    {
                        dt = DataType.Time;
                    }
                    else if (len == 5)
                    {
                        dt = DataType.Date;
                    }
                    GXDataInfo info = new GXDataInfo();
                    info.Type = dt;
                    GXCommon.GetData(settings, new GXByteBuffer(tmp), info);
                }
            }
            // Get object count.
            int cnt = GXCommon.GetObjectCount(data);

            if (xml != null)
            {
                xml.AppendStartTag(Command.AccessRequest);
                xml.AppendLine(TranslatorTags.LongInvokeId, "Value", xml.IntegerToHex(invokeId, 2));
                xml.AppendLine(TranslatorTags.DateTime, "Value", GXCommon.ToHex(tmp, false));
                xml.AppendStartTag(TranslatorTags.AccessRequestBody);
                xml.AppendStartTag(TranslatorTags.ListOfAccessRequestSpecification, "Qty",
                                   xml.IntegerToHex(cnt, 2));
            }
            AccessServiceCommandType type;

            for (int pos = 0; pos != cnt; ++pos)
            {
                type = (AccessServiceCommandType)data.GetUInt8();
                if (!(type == AccessServiceCommandType.Get ||
                      type == AccessServiceCommandType.Set ||
                      type == AccessServiceCommandType.Action))
                {
                    throw new ArgumentException("Invalid access service command type.");
                }
                // CI
                ObjectType ci = (ObjectType)data.GetUInt16();
                byte[]     ln = new byte[6];
                data.Get(ln);
                // Attribute Id
                byte attributeIndex = data.GetUInt8();
                if (xml != null)
                {
                    xml.AppendStartTag(TranslatorTags.AccessRequestSpecification);
                    xml.AppendStartTag(Command.AccessRequest, type);
                    AppendAttributeDescriptor(xml, (int)ci, ln, attributeIndex);
                    xml.AppendEndTag(Command.AccessRequest, type);
                    xml.AppendEndTag(TranslatorTags.AccessRequestSpecification);
                }
            }
            if (xml != null)
            {
                xml.AppendEndTag(TranslatorTags.ListOfAccessRequestSpecification);
                xml.AppendStartTag(TranslatorTags.AccessRequestListOfData, "Qty", xml.IntegerToHex(cnt, 2));
            }
            // Get data count.
            cnt = GXCommon.GetObjectCount(data);
            for (int pos = 0; pos != cnt; ++pos)
            {
                GXDataInfo di = new GXDataInfo();
                di.xml = xml;
                if (xml != null && xml.OutputType == TranslatorOutputType.StandardXml)
                {
                    xml.AppendStartTag(Command.WriteRequest, SingleReadResponse.Data);
                }
                object value = GXCommon.GetData(settings, data, di);
                if (!di.Complete)
                {
                    value = GXCommon.ToHex(data.Data, false, data.Position, data.Size - data.Position);
                }
                else if (value is byte[])
                {
                    value = GXCommon.ToHex((byte[])value, false);
                }
                if (xml != null && xml
                    .OutputType == TranslatorOutputType.StandardXml)
                {
                    xml.AppendEndTag(Command.WriteRequest, SingleReadResponse.Data);
                }
            }
            if (xml != null)
            {
                xml.AppendEndTag(TranslatorTags.AccessRequestListOfData);
                xml.AppendEndTag(TranslatorTags.AccessRequestBody);
                xml.AppendEndTag(Command.AccessRequest);
            }
        }
Ejemplo n.º 23
0
        private void Init(byte[] data)
        {
            rawData    = data;
            Attributes = new List <KeyValuePair <PkcsObjectIdentifier, object[]> >();
            GXAsn1Sequence seq = (GXAsn1Sequence)GXAsn1Converter.FromByteArray(data);

            if (seq.Count < 3)
            {
                throw new System.ArgumentException("Wrong number of elements in sequence.");
            }
            if (!(seq[0] is GXAsn1Sequence))
            {
                PkcsType type = GXAsn1Converter.GetCertificateType(data, seq);
                switch (type)
                {
                case PkcsType.Pkcs8:
                    throw new GXDLMSCertificateException("Invalid Certificate. This is PKCS 8, not PKCS 10.");

                case PkcsType.x509Certificate:
                    throw new GXDLMSCertificateException("Invalid Certificate. This is PKCS x509 certificate, not PKCS 10.");
                }
                throw new GXDLMSCertificateException("Invalid Certificate Version.");
            }
            /////////////////////////////
            // CertificationRequestInfo ::= SEQUENCE {
            // version INTEGER { v1(0) } (v1,...),
            // subject Name,
            // subjectPKInfo SubjectPublicKeyInfo{{ PKInfoAlgorithms }},
            // attributes [0] Attributes{{ CRIAttributes }}
            // }

            GXAsn1Sequence reqInfo = (GXAsn1Sequence)seq[0];

            Version = (CertificateVersion)(sbyte)reqInfo[0];
            Subject = GXAsn1Converter.GetSubject((GXAsn1Sequence)reqInfo[1]);
            // subject Public key info.
            GXAsn1Sequence subjectPKInfo = (GXAsn1Sequence)reqInfo[2];

            if (reqInfo.Count > 3)
            {
                //PkcsObjectIdentifier
                foreach (GXAsn1Sequence it in (GXAsn1Context)reqInfo[3])
                {
                    List <object> values = new List <object>();
                    foreach (object v in (List <object>)((KeyValuePair <object, object>)it[1]).Key)
                    {
                        values.Add(v);
                    }
                    Attributes.Add(new KeyValuePair <PkcsObjectIdentifier, object[]>(PkcsObjectIdentifierConverter.FromString(it[0].ToString()), values.ToArray()));
                }
            }
            GXAsn1Sequence tmp = (GXAsn1Sequence)subjectPKInfo[0];

            Algorithm = X9ObjectIdentifierConverter.FromString(tmp[0].ToString());
            if (Algorithm != X9ObjectIdentifier.IdECPublicKey)
            {
                object algorithm = Algorithm;
                if (Algorithm == X9ObjectIdentifier.None)
                {
                    algorithm = PkcsObjectIdentifierConverter.FromString(tmp[0].ToString());
                    if ((PkcsObjectIdentifier)algorithm == PkcsObjectIdentifier.None)
                    {
                        algorithm = tmp[0].ToString();
                    }
                }
                throw new Exception("Invalid PKCS #10 certificate algorithm. " + algorithm);
            }
            PublicKey = GXPublicKey.FromRawBytes(((GXAsn1BitString)subjectPKInfo[1]).Value);
            GXEcdsa.Validate(PublicKey);
            /////////////////////////////
            // signatureAlgorithm
            GXAsn1Sequence sign = (GXAsn1Sequence)seq[1];

            SignatureAlgorithm = HashAlgorithmConverter.FromString(sign[0].ToString());
            if (SignatureAlgorithm != HashAlgorithm.Sha256WithEcdsa && SignatureAlgorithm != HashAlgorithm.Sha384WithEcdsa)
            {
                throw new GXDLMSCertificateException("Invalid signature algorithm. " + sign[0].ToString());
            }
            if (sign.Count != 1)
            {
                SignatureParameters = sign[1];
            }
            /////////////////////////////
            // signature
            //Get raw data
            GXByteBuffer tmp2 = new GXByteBuffer();

            tmp2.Set(data);
            GXAsn1Converter.GetNext(tmp2);
            tmp2.Size     = tmp2.Position;
            tmp2.Position = 1;
            GXCommon.GetObjectCount(tmp2);
            //Get signature.
            Signature = ((GXAsn1BitString)seq[2]).Value;
            GXEcdsa        e    = new GXEcdsa(PublicKey);
            GXAsn1Sequence tmp3 = (GXAsn1Sequence)GXAsn1Converter.FromByteArray(Signature);
            GXByteBuffer   bb   = new GXByteBuffer();
            int            size = SignatureAlgorithm == HashAlgorithm.Sha256WithEcdsa ? 32 : 48;

            //Some implementations might add extra byte. It must removed.
            bb.Set(((GXAsn1Integer)tmp3[0]).Value, ((GXAsn1Integer)tmp3[0]).Value.Length == size ? 0 : 1, size);
            bb.Set(((GXAsn1Integer)tmp3[1]).Value, ((GXAsn1Integer)tmp3[1]).Value.Length == size ? 0 : 1, size);
            if (!e.Verify(bb.Array(), tmp2.SubArray(tmp2.Position, tmp2.Available)))
            {
                throw new ArgumentException("Invalid Signature.");
            }
        }