Beispiel #1
0
        /// <summary>
        /// Generate KDF.
        /// </summary>
        /// <param name="securitySuite">Security suite.</param>
        /// <param name="z">z Shared Secret.</param>
        /// <param name="otherInfo">Other info.</param>
        /// <returns></returns>
        public static byte[] GenerateKDF(SecuritySuite securitySuite, byte[] z, byte[] otherInfo)
        {
            GXByteBuffer bb = new GXByteBuffer();

            bb.SetUInt32(1);
            bb.Set(z);
            bb.Set(otherInfo);
            if (securitySuite == SecuritySuite.Ecdsa256)
            {
                using (SHA256 sha = new SHA256CryptoServiceProvider())
                {
                    return(sha.ComputeHash(bb.Array()));
                }
            }
            else if (securitySuite == SecuritySuite.Ecdsa384)
            {
                using (SHA384 sha = new SHA384CryptoServiceProvider())
                {
                    return(sha.ComputeHash(bb.Array()));
                }
            }
            else
            {
                throw new ArgumentOutOfRangeException("Invalid sevurity suite.");
            }
        }
Beispiel #2
0
        /// <summary>
        /// Generate User information initiate request.
        /// </summary>
        /// <param name="settings">DLMS settings.</param>
        /// <param name="cipher"></param>
        /// <param name="data"></param>
        private static void GetInitiateRequest(GXDLMSSettings settings, GXICipher cipher, GXByteBuffer data)
        {
            // Tag for xDLMS-Initiate request
            data.SetUInt8(GXCommon.InitialRequest);
            // Usage field for dedicated-key component. Not used
            data.SetUInt8(0x00);
            //encoding of the response-allowed component (BOOLEAN DEFAULT TRUE)
            // usage flag (FALSE, default value TRUE conveyed)
            data.SetUInt8(0);

            // Usage field of the proposed-quality-of-service component. Not used
            data.SetUInt8(0x00);
            data.SetUInt8(settings.DLMSVersion);
            // Tag for conformance block
            data.SetUInt8(0x5F);
            data.SetUInt8(0x1F);
            // length of the conformance block
            data.SetUInt8(0x04);
            // encoding the number of unused bits in the bit string
            data.SetUInt8(0x00);
            if (settings.UseLogicalNameReferencing)
            {
                data.Set(settings.LnSettings.ConformanceBlock);
            }
            else
            {
                data.Set(settings.SnSettings.ConformanceBlock);
            }
            data.SetUInt16(settings.MaxReceivePDUSize);
        }
        /// <summary>
        /// Agree on global unicast encryption key.
        /// </summary>
        /// <param name="client"> DLMS client that is used to generate action.</param>
        /// <param name="key"> List of keys.</param>
        /// <returns>Generated action.</returns>
        public byte[][] KeyAgreement(GXDLMSSecureClient client)
        {
            if (Version == 0)
            {
                throw new ArgumentException("Public and private key isn't implemented for version 0.");
            }
            if (client.Ciphering.EphemeralKeyPair.Value == null)
            {
                throw new ArgumentException("Invalid Ephemeral key.");
            }
            if (client.Ciphering.SigningKeyPair.Value == null)
            {
                throw new ArgumentException("Invalid Signiture key.");
            }
            GXByteBuffer bb = new GXByteBuffer();

            //Add Ephemeral public key.
            bb.Set(client.Ciphering.EphemeralKeyPair.Value.RawValue, 1, client.Ciphering.EphemeralKeyPair.Value.RawValue.Length - 1);
            //Add signature.
            byte[] sign = GXSecure.GetEphemeralPublicKeySignature(0, client.Ciphering.EphemeralKeyPair.Value,
                                                                  client.Ciphering.SigningKeyPair.Key);
            bb.Set(sign);
            List <KeyValuePair <GlobalKeyType, byte[]> > list = new List <KeyValuePair <GlobalKeyType, byte[]> >();

            list.Add(new KeyValuePair <GlobalKeyType, byte[]>(GlobalKeyType.UnicastEncryption, bb.Array()));
            return(KeyAgreement(client, list));
        }
Beispiel #4
0
 void OnShowDlg(GXActionArgs arg)
 {
     if (InvokeRequired)
     {
         BeginInvoke(new ShowDlgEventHandler(OnShowDlg), arg).AsyncWaitHandle.WaitOne();
     }
     else
     {
         GXDLMSIp6Setup target = Target as GXDLMSIp6Setup;
         if (arg.Index == 5)
         {
             GXClockPresetTimeDlg dlg = new GXClockPresetTimeDlg();
             if (dlg.ShowDialog(this) == DialogResult.OK)
             {
                 GXByteBuffer bb = new GXByteBuffer();
                 bb.SetUInt8((byte)DataType.Structure);
                 bb.SetUInt8(4);
                 //Add data type and length.
                 bb.SetUInt8((byte)DataType.OctetString);
                 bb.SetUInt8(12);
                 bb.Set(GXDLMSTranslator.HexToBytes(dlg.PresetTime.ToHex(false, GXDlmsUi.UseMeterTimeZone)));
                 //Add data type and length.
                 bb.SetUInt8((byte)DataType.OctetString);
                 bb.SetUInt8(12);
                 bb.Set(GXDLMSTranslator.HexToBytes(dlg.IntervalStart.ToHex(false, GXDlmsUi.UseMeterTimeZone)));
                 //Add data type and length.
                 bb.SetUInt8((byte)DataType.OctetString);
                 bb.SetUInt8(12);
                 bb.Set(GXDLMSTranslator.HexToBytes(dlg.IntervalEnd.ToHex(false, GXDlmsUi.UseMeterTimeZone)));
                 arg.Value = bb.Array();
             }
             else
             {
                 arg.Handled = true;
             }
         }
         else if (arg.Index == 6)
         {
             GXTextDlg dlg = new GXTextDlg("Shift Time", "Shift Time (s):", "", typeof(Int16));
             if (dlg.ShowDialog(this) == DialogResult.OK)
             {
                 arg.Value = Int16.Parse(dlg.GetValue());
             }
             else
             {
                 arg.Handled = true;
             }
         }
         else
         {
             arg.Handled = true;
         }
     }
 }
Beispiel #5
0
        /// <summary>
        /// Code application context name.
        /// </summary>
        /// <param name="settings">DLMS settings.</param>
        /// <param name="data">Byte buffer where data is saved.</param>
        /// <param name="cipher">Is ciphering settings.</param>
        private static void GenerateApplicationContextName(GXDLMSSettings settings, GXByteBuffer data, GXICipher cipher)
        {
            //Application context name tag
            data.SetUInt8(((byte)BerType.Context | (byte)BerType.Constructed | (byte)PduType.ApplicationContextName));
            //Len
            data.SetUInt8(0x09);
            data.SetUInt8(BerType.ObjectIdentifier);
            //Len
            data.SetUInt8(0x07);
            bool ciphered = cipher != null && cipher.IsCiphered();

            if (settings.UseLogicalNameReferencing)
            {
                if (ciphered)
                {
                    data.Set(GXCommon.LogicalNameObjectIdWithCiphering);
                }
                else
                {
                    data.Set(GXCommon.LogicalNameObjectID);
                }
            }
            else
            {
                if (ciphered)
                {
                    data.Set(GXCommon.ShortNameObjectIdWithCiphering);
                }
                else
                {
                    data.Set(GXCommon.ShortNameObjectID);
                }
            }
            //Add system title if cipher or GMAC authentication is used..
            if (!settings.IsServer && (ciphered || settings.Authentication == Authentication.HighGMAC))
            {
                if (cipher.SystemTitle == null || cipher.SystemTitle.Length == 0)
                {
                    throw new ArgumentNullException("SystemTitle");
                }
                //Add calling-AP-title
                data.SetUInt8(((byte)BerType.Context | (byte)BerType.Constructed | 6));
                //LEN
                data.SetUInt8((byte)(2 + cipher.SystemTitle.Length));
                data.SetUInt8((byte)BerType.OctetString);
                //LEN
                data.SetUInt8((byte)cipher.SystemTitle.Length);
                data.Set(cipher.SystemTitle);
            }
        }
Beispiel #6
0
        ///<summary>
        ///Retrieves the string that indicates the level of authentication, if any.
        ///</summary>
        private static void GetAuthenticationString(GXDLMSSettings settings, GXByteBuffer data)
        {
            //If authentication is used.
            if (settings.Authentication != Authentication.None)
            {
                //Add sender ACSE-requirements field component.
                data.SetUInt8((byte)BerType.Context | (byte)PduType.SenderAcseRequirements);
                data.SetUInt8(2);
                data.SetUInt8(BerType.BitString | BerType.OctetString);
                data.SetUInt8(0x80);

                data.SetUInt8((byte)BerType.Context | (byte)PduType.MechanismName);
                //Len
                data.SetUInt8(7);
                // OBJECT IDENTIFIER
                byte[] p = { (byte)0x60, (byte)0x85, (byte)0x74, (byte)0x05, (byte)0x08, (byte)0x02, (byte)settings.Authentication };
                data.Set(p);
                //Add Calling authentication information.
                int    len = 0;
                byte[] pw  = null;
                if (settings.Authentication < Authentication.HighMD5)
                {
                    pw = settings.Password;
                    if (pw != null)
                    {
                        len = pw.Length;
                    }
                }
                else
                {
                    pw = settings.CtoSChallenge;
                    if (pw != null)
                    {
                        len = pw.Length;
                    }
                }
                data.SetUInt8((byte)BerType.Context | (byte)BerType.Constructed | (byte)PduType.CallingAuthenticationValue); //0xAC
                //Len
                data.SetUInt8((byte)(2 + len));
                //Add authentication information.
                data.SetUInt8((byte)BerType.Context);
                //Len.
                data.SetUInt8((byte)len);
                if (pw != null)
                {
                    data.Set(pw);
                }
            }
        }
Beispiel #7
0
        /// <summary>
        /// Sign given data using public and private key.
        /// </summary>
        /// <param name="data">Data to sign.</param>
        /// <returns>Signature</returns>
        public byte[] Sign(byte[] data)
        {
            if (PrivateKey == null)
            {
                throw new ArgumentException("Invalid private key.");
            }
            GXBigInteger msg;

            if (PrivateKey.Scheme == Ecc.P256)
            {
                using (SHA256 sha = new SHA256CryptoServiceProvider())
                {
                    msg = new GXBigInteger(sha.ComputeHash(data));
                }
            }
            else
            {
                using (SHA384 sha = new SHA384CryptoServiceProvider())
                {
                    msg = new GXBigInteger(sha.ComputeHash(data));
                }
            }
            GXBigInteger pk = new GXBigInteger(PrivateKey.RawValue);
            GXEccPoint   p;
            GXBigInteger n;
            GXBigInteger r;
            GXBigInteger s;

            do
            {
                n = GetRandomNumber(PrivateKey.Scheme);
                p = new GXEccPoint(curve.G.x, curve.G.y, new GXBigInteger(1));
                Multiply(p, n, curve.N, curve.A, curve.P);
                r = p.x;
                r.Mod(curve.N);
                n.Inv(curve.N);
                //s
                s = new GXBigInteger(r);
                s.Multiply(pk);
                s.Add(msg);
                s.Multiply(n);
                s.Mod(curve.N);
            } while (r.IsZero || s.IsZero);
            GXByteBuffer signature = new GXByteBuffer();

            signature.Set(r.ToArray());
            signature.Set(s.ToArray());
            return(signature.Array());
        }
 internal static void SetValue(GXByteBuffer buff, object data)
 {
     GXByteBuffer tmp = new GXByteBuffer();
     tmp.Add(data);
     buff.Add((byte)tmp.Size);
     buff.Set(tmp.Array());
 }
Beispiel #9
0
        static public void WriteLog(string text, byte[] value)
        {
            string str = DateTime.Now.ToLongTimeString() + " " + text;

            //Show data as hex.
            if ((LogLevel & 1) != 0)
            {
                if (value != null)
                {
                    str += "\r\n" + GXCommon.ToHex(value, true);
                }
                System.Diagnostics.Trace.WriteLine(str);
            }
            //Show data as xml.
            if ((LogLevel & 2) != 0)
            {
                receivedTraceData.Set(value);
                try
                {
                    GXByteBuffer  pdu  = new GXByteBuffer();
                    InterfaceType type = GXDLMSTranslator.GetDlmsFraming(receivedTraceData);
                    if (translator.FindNextFrame(receivedTraceData, pdu, type))
                    {
                        System.Diagnostics.Trace.WriteLine(translator.MessageToXml(receivedTraceData));
                        receivedTraceData.Clear();
                    }
                }
                catch (Exception)
                {
                    receivedTraceData.Clear();
                }
            }
        }
Beispiel #10
0
 /// <summary>
 /// Generate user information.
 /// </summary>
 /// <param name="settings">DLMS settings.</param>
 /// <param name="cipher"></param>
 /// <param name="data">Generated user information.</param>
 static internal void GenerateUserInformation(GXDLMSSettings settings, GXICipher cipher, GXByteBuffer data)
 {
     data.SetUInt8((byte)BerType.Context | (byte)BerType.Constructed | (byte)PduType.UserInformation);
     if (cipher == null || !cipher.IsCiphered())
     {
         //Length for AARQ user field
         data.SetUInt8(0x10);
         //Coding the choice for user-information (Octet STRING, universal)
         data.SetUInt8(BerType.OctetString);
         //Length
         data.SetUInt8(0x0E);
         GetInitiateRequest(settings, cipher, data);
     }
     else
     {
         GXByteBuffer tmp = new GXByteBuffer();
         GetInitiateRequest(settings, cipher, tmp);
         byte[] crypted = cipher.Encrypt(0x21, cipher.SystemTitle, tmp.Array());
         //Length for AARQ user field
         data.SetUInt8((byte)(2 + crypted.Length));
         //Coding the choice for user-information (Octet STRING, universal)
         data.SetUInt8(BerType.OctetString);
         data.SetUInt8((byte)crypted.Length);
         data.Set(crypted);
     }
 }
Beispiel #11
0
        /// <summary>
        /// Read DLMS Data from the device.
        /// </summary>
        /// <remarks>
        /// If access is denied return null.
        /// </remarks>
        /// <param name="data">Data to send.</param>
        /// <returns>Received data.</returns>
        public void ReadDLMSPacket(byte[] data, GXReplyData reply)
        {
            if ((data == null || data.Length == 0) && !reply.IsStreaming())
            {
                return;
            }
            GXReplyData notify = new GXReplyData();

            reply.Error = 0;
            object eop = (byte)0x7E;

            //In network connection terminator is not used.
            if (client.InterfaceType == InterfaceType.WRAPPER && !parent.UseRemoteSerial)
            {
                eop = null;
            }
            ReceiveParameters <byte[]> p = new ReceiveParameters <byte[]>()
            {
                AllData  = false,
                Eop      = eop,
                Count    = 5,
                WaitTime = parent.WaitTime * 1000,
            };
            var          answer = Send(data);
            GXByteBuffer rd     = new GXByteBuffer(answer.Body);

            try
            {
                //Loop until whole COSEM packet is received.
                while (!client.GetData(rd, reply, notify))
                {
                    p.Reply = null;
                    if (notify.Data.Size != 0)
                    {
                        // Handle notify.
                        if (!notify.IsMoreData)
                        {
                            rd.Trim();
                            notify.Clear();
                            p.Eop = eop;
                        }
                        continue;
                    }
                    //If Eop is not set read one byte at time.
                    if (p.Eop == null)
                    {
                        p.Count = client.GetFrameSize(rd);
                    }
                    rd.Set(p.Reply);
                }
            }
            catch (Exception ex)
            {
                throw ex;
            }
            if (reply.Error != 0)
            {
                throw new GXDLMSException(reply.Error);
            }
        }
        public override sealed string ToString()
        {
            string str;

            switch (Value.Length)
            {
            case 1:
                str = Convert.ToString(ToByte());
                break;

            case 2:
                str = Convert.ToString(ToShort());
                break;

            case 4:
                str = Convert.ToString(ToInt());
                break;

            case 8:
                str = Convert.ToString(ToLong());
                break;

            default:
                GXByteBuffer bb = new GXByteBuffer();
                bb.Set(Value);
                str = bb.GetUInt64().ToString();
                break;
            }
            return(str);
        }
Beispiel #13
0
 internal static byte[] Decrypt(AesGcmParameter p, GXByteBuffer data)
 {
     byte[] tmp = GXDLMSChippering.DecryptAesGcm(p, data);
     data.Clear();
     data.Set(tmp);
     return(tmp);
 }
 /// <summary>
 /// Update template description.
 /// </summary>
 public void UpdateTemplateDescription()
 {
     lock (this)
     {
         GXByteBuffer bb = new GXByteBuffer();
         Buffer = null;
         bb.SetUInt8((byte)DataType.Structure);
         GXCommon.SetObjectCount(CaptureObjects.Count, bb);
         foreach (GXKeyValuePair <GXDLMSObject, GXDLMSCaptureObject> it in CaptureObjects)
         {
             DataType dt = (it.Key as IGXDLMSBase).GetDataType(it.Value.AttributeIndex);
             if (dt == DataType.Array || dt == DataType.Structure)
             {
                 ValueEventArgs e    = new ValueEventArgs(null, it.Value.AttributeIndex, 0, null);
                 GXByteBuffer   data = new GXByteBuffer();
                 object         v    = ((IGXDLMSBase)it.Key).GetValue(null, e);
                 if (v is byte[])
                 {
                     data.Set((byte[])v);
                 }
                 else
                 {
                     data = (GXByteBuffer)v;
                 }
                 UpdateTemplateDescription(bb, data, ((GXDLMSCaptureObject)it.Value).DataIndex - 1);
             }
             else
             {
                 bb.SetUInt8(dt);
             }
         }
         TemplateDescription = bb.Array();
     }
 }
 /// <summary>
 /// Constructor.
 /// </summary>
 /// <param name="forTarget"></param>
 /// <param name="forCommand"></param>
 /// <param name="forType"></param>
 public GXDLMSLongTransaction(ValueEventArgs[] forTargets, Command forCommand, GXByteBuffer forData)
 {
     targets = forTargets;
     command = forCommand;
     data = new GXByteBuffer();
     data.Set(forData.Data, forData.Position, forData.Size - forData.Position);
 }
 /// <summary>
 /// Constructor.
 /// </summary>
 /// <param name="forTarget"></param>
 /// <param name="forCommand"></param>
 /// <param name="forData"></param>
 public GXDLMSLongTransaction(ValueEventArgs[] forTargets, Command forCommand, GXByteBuffer forData)
 {
     targets = forTargets;
     command = forCommand;
     data    = new GXByteBuffer();
     data.Set(forData.Data, forData.Position, forData.Size - forData.Position);
 }
Beispiel #17
0
        /// <summary>
        /// Check that this is correct public key.
        /// </summary>
        /// <remarks>
        /// This method can be used to verify that public and private key are on the curve.
        /// </remarks>
        public static void Validate(GXPublicKey publicKey)
        {
            if (publicKey == null)
            {
                throw new ArgumentNullException("Invalid public key.");
            }
            GXByteBuffer bb = new GXByteBuffer();

            bb.Set(publicKey.RawValue);
            int          size  = SchemeSize(publicKey.Scheme);
            GXBigInteger x     = new GXBigInteger(bb.SubArray(1, size));
            GXBigInteger y     = new GXBigInteger(bb.SubArray(1 + size, size));
            GXCurve      curve = new GXCurve(publicKey.Scheme);

            y.Multiply(y);
            y.Mod(curve.P);

            GXBigInteger tmpX = new GXBigInteger(x);

            tmpX.Multiply(x);
            tmpX.Mod(curve.P);
            tmpX.Add(curve.A);
            tmpX.Multiply(x);
            tmpX.Add(curve.B);
            tmpX.Mod(curve.P);
            if (y.Compare(tmpX) != 0)
            {
                throw new ArgumentException("Public key validate failed. Public key is not valid ECDSA public key.");
            }
        }
Beispiel #18
0
        /// <summary>
        /// Constructor value.
        /// </summary>
        /// <param name="value">Byte array Data in MSB format.</param>
        public GXBigInteger(byte[] value)
        {
            GXByteBuffer bb = new GXByteBuffer();

            bb.Set(value);
            FromByteBuffer(bb);
        }
        internal static void SetValue(GXByteBuffer buff, object data)
        {
            GXByteBuffer tmp = new GXByteBuffer();

            tmp.Add(data);
            buff.Add((byte)tmp.Size);
            buff.Set(tmp.Array());
        }
Beispiel #20
0
        /// <summary>
        /// Try to find client and server address from the meter.
        /// </summary>
        private void DiscoverMeters(object sender, GXAsyncWork work, object[] parameters)
        {
            GXDLMSClient cl = new GXDLMSClient(true, 16, 1, Authentication.None, null, (InterfaceType)Settings.Default.PlcInterface);

            byte[] data = cl.Plc.DiscoverRequest();
            ReceiveParameters <byte[]> p = new ReceiveParameters <byte[]>()
            {
                AllData  = false,
                Count    = 8,
                WaitTime = 10000,
            };
            DateTime     start = DateTime.Now;
            GXByteBuffer rd    = new GXByteBuffer();

            lock (media.Synchronous)
            {
                if (data != null)
                {
                    media.Send(data, null);
                    start = DateTime.Now;
                }
                GXReplyData reply = new GXReplyData();
                rd = new GXByteBuffer(p.Reply);
                try
                {
                    while (!work.IsCanceled)
                    {
                        p.Reply = null;
                        //If Eop is not set read one byte at time.
                        if (p.Eop == null)
                        {
                            p.Count = cl.GetFrameSize(rd);
                        }
                        if (!media.IsOpen)
                        {
                            throw new InvalidOperationException("Media is closed.");
                        }
                        if (!media.Receive(p))
                        {
                            //It's OK if there is no reply. Read again
                            continue;
                        }
                        rd.Position = 0;
                        rd.Set(p.Reply);
                        if (cl.GetData(rd, reply))
                        {
                            List <GXDLMSPlcMeterInfo> list = cl.Plc.ParseDiscover(reply.Data, (UInt16)reply.TargetAddress, (UInt16)reply.SourceAddress);
                            BeginInvoke(new AppendMeterEventHandler(OnAppendMeter), list);
                        }
                    }
                }
                catch (Exception)
                {
                    //Throw original exception.
                    throw;
                }
            }
        }
Beispiel #21
0
        Security GXICipher.Decrypt(byte[] title, GXByteBuffer data)
        {
            AesGcmParameter p = new AesGcmParameter(title, BlockCipherKey, AuthenticationKey);

            byte[] tmp = GXDLMSChippering.DecryptAesGcm(p, data);
            data.Clear();
            data.Set(tmp);
            return(p.Security);
        }
 /// <summary>
 /// Copies the values of the objects to capture
 /// into the buffer by reading capture objects.
 /// </summary>
 internal void Capture(GXDLMSServer server)
 {
     lock (this)
     {
         GXByteBuffer     bb   = new GXByteBuffer();
         ValueEventArgs[] args = new ValueEventArgs[] { new ValueEventArgs(server, this, 2, 0, null) };
         Buffer = null;
         if (server != null)
         {
             server.PreGet(args);
         }
         if (!args[0].Handled)
         {
             foreach (GXKeyValuePair <GXDLMSObject, GXDLMSCaptureObject> it in CaptureObjects)
             {
                 ValueEventArgs e     = new ValueEventArgs(server, it.Key, it.Value.AttributeIndex, 0, null);
                 object         value = (it.Key as IGXDLMSBase).GetValue(server == null ? null : server.Settings, e);
                 DataType       dt    = (it.Key as IGXDLMSBase).GetDataType(it.Value.AttributeIndex);
                 if ((value is byte[] || value is GXByteBuffer[]) && (dt == DataType.Structure || dt == DataType.Array))
                 {
                     GXByteBuffer tmp;
                     if (value is byte[])
                     {
                         tmp = new GXByteBuffer((byte[])value);
                     }
                     else
                     {
                         tmp = (GXByteBuffer)value;
                     }
                     CaptureArray(server, tmp, bb, it.Value.DataIndex - 1);
                 }
                 else
                 {
                     GXByteBuffer tmp = new GXByteBuffer();
                     GXCommon.SetData(server == null ? null : server.Settings, tmp, dt, value);
                     //If data is empty.
                     if (tmp.Size == 1)
                     {
                         bb.SetUInt8(0);
                     }
                     else
                     {
                         tmp.Position = 1;
                         bb.Set(tmp);
                     }
                 }
             }
             Buffer = bb.Array();
         }
         if (server != null)
         {
             server.PostGet(args);
             server.NotifyAction(args);
             server.NotifyPostAction(args);
         }
     }
 }
        /// <summary>
        /// Convert compact data buffer to array of values.
        /// </summary>
        /// <param name="templateDescription">Template description byte array.</param>
        /// <param name="buffer">Buffer byte array.</param>
        /// <returns>Values from byte buffer.</returns>
        public List <object> GetValues(byte[] templateDescription, byte[] buffer)
        {
            //If templateDescription or buffer is not given.
            if (templateDescription == null || buffer == null || templateDescription.Length == 0 || buffer.Length == 0)
            {
                throw new ArgumentException();
            }
            GXDataInfo   info = new GXDataInfo();
            object       tmp;
            GXByteBuffer data = new GXByteBuffer();

            data.Set(templateDescription);
            GXCommon.SetObjectCount(buffer.Length, data);
            data.Set(buffer);
            info.Type = DataType.CompactArray;
            tmp       = GXCommon.GetData(null, data, info);
            return((List <object>)tmp);
        }
        /// <summary>
        /// Get public key from private key.
        /// </summary>
        /// <param name="scheme">Used scheme.</param>
        /// <param name="privateKey">Private key bytes.</param>
        /// <returns>Public key.</returns>
        public GXPublicKey GetPublicKey()
        {
            GXBigInteger secret = new GXBigInteger(RawValue);
            GXCurve      curve  = new GXCurve(Scheme);
            GXEccPoint   p      = new GXEccPoint(curve.G.x, curve.G.y, new GXBigInteger(1));

            p = GXEcdsa.JacobianMultiply(p, secret, curve.N, curve.A, curve.P);
            GXEcdsa.FromJacobian(p, curve.P);
            GXByteBuffer key = new GXByteBuffer(65);

            //Public key is un-compressed format.
            key.SetUInt8(4);
            byte[] tmp = p.x.ToArray();
            key.Set(tmp, tmp.Length % 32, 32);
            tmp = p.y.ToArray();
            key.Set(tmp, tmp.Length % 32, 32);
            return(GXPublicKey.FromRawBytes(key.Array()));
        }
        public static List <object> GetData(byte[] columns, byte[] value, bool AppendAA)
        {
            if (columns == null || columns.Length == 0 ||
                value == null || value.Length == 0)
            {
                return(new GXArray());
            }
            List <DataType> list = new List <DataType>();
            GXDataInfo      info = new GXDataInfo();

            info.AppendAA = AppendAA;
            GXByteBuffer bb = new GXByteBuffer();

            bb.Set(columns);
            GXCommon.SetObjectCount(value.Length, bb);
            bb.Set(value);
            List <object> tmp = (List <object>)GXCommon.GetCompactArray(null, bb, info, false);

            return(tmp);
        }
 /// <summary>
 /// Get public key from private key.
 /// </summary>
 /// <param name="scheme">Used scheme.</param>
 /// <param name="privateKey">Private key bytes.</param>
 /// <returns>Public key.</returns>
 public GXPublicKey GetPublicKey()
 {
     if (publicKey == null)
     {
         GXBigInteger pk    = new GXBigInteger(RawValue);
         GXCurve      curve = new GXCurve(Scheme);
         GXEccPoint   p     = new GXEccPoint(curve.G.x, curve.G.y, new GXBigInteger(1));
         p = GXEcdsa.JacobianMultiply(p, pk, curve.N, curve.A, curve.P);
         GXEcdsa.FromJacobian(p, curve.P);
         GXByteBuffer key = new GXByteBuffer(65);
         //Public key is un-compressed format.
         key.SetUInt8(4);
         byte[] tmp  = p.x.ToArray();
         int    size = Scheme == Ecc.P256 ? 32 : 48;
         key.Set(tmp, tmp.Length % size, size);
         tmp = p.y.ToArray();
         key.Set(tmp, tmp.Length % size, size);
         publicKey = GXPublicKey.FromRawBytes(key.Array());
     }
     return(publicKey);
 }
        /// <summary>
        /// Sends data to the M-Bus slave device.
        /// </summary>
        /// <param name="client">DLMS client settings.</param>
        /// <param name="data">data to send</param>
        /// <returns>Generated DLMS data.</returns>
        public byte[][] SendData(GXDLMSClient client, GXMBusClientData[] data)
        {
            GXByteBuffer bb = new GXByteBuffer();

            bb.SetUInt8(DataType.Array);
            bb.SetUInt8(DataType.Structure);
            GXCommon.SetObjectCount(data.Length, bb);
            foreach (GXMBusClientData it in data)
            {
                bb.SetUInt8(DataType.Structure);
                bb.SetUInt8(3);
                bb.SetUInt8(DataType.OctetString);
                GXCommon.SetObjectCount(it.DataInformation.Length, bb);
                bb.Set(it.DataInformation);
                bb.SetUInt8(DataType.OctetString);
                GXCommon.SetObjectCount(it.ValueInformation.Length, bb);
                bb.Set(it.ValueInformation);
                GXCommon.SetData(client.Settings, bb, GXDLMSConverter.GetDLMSDataType(it.Data), it.Data);
            }
            return(client.Method(this, 6, bb.Array(), DataType.Array));
        }
Beispiel #28
0
        /// <summary>
        /// Generate GMAC password from given challenge.
        /// </summary>
        /// <param name="challenge"></param>
        /// <returns></returns>
        public byte[] GenerateGmacPassword(byte[] challenge)
        {
            AesGcmParameter p = new AesGcmParameter(0x10, Gurux.DLMS.Enums.Security.Authentication, InvocationCounter,
                                                    systemTitle, BlockCipherKey, AuthenticationKey);
            GXByteBuffer bb = new GXByteBuffer();

            GXDLMSChippering.EncryptAesGcm(p, challenge);
            bb.SetUInt8(0x10);
            bb.SetUInt32(InvocationCounter);
            bb.Set(p.CountTag);
            return(bb.Array());
        }
Beispiel #29
0
        /// <summary>
        /// Generate KDF.
        /// </summary>
        /// <param name="securitySuite">Used security suite.</param>
        /// <param name="z">Shared Secret.</param>
        /// <param name="algorithmID">Algorithm ID.</param>
        /// <param name="partyUInfo">Sender system title.</param>
        /// <param name="partyVInfo">Receiver system title.</param>
        /// <param name="suppPubInfo">Not used in DLMS.</param>
        /// <param name="suppPrivInfo">Not used in DLMS.</param>
        /// <returns></returns>
        public static byte[] GenerateKDF(SecuritySuite securitySuite, byte[] z,
                                         AlgorithmId algorithmID,
                                         byte[] partyUInfo,
                                         byte[] partyVInfo,
                                         byte[] suppPubInfo,
                                         byte[] suppPrivInfo)
        {
            GXByteBuffer bb = new GXByteBuffer();

            bb.Set(new byte[] { 0x60, 0x85, 0x74, 0x05, 0x08, 0x03, (byte)algorithmID });
            bb.Set(partyUInfo);
            bb.Set(partyVInfo);
            if (suppPubInfo != null)
            {
                bb.Set(suppPubInfo);
            }
            if (suppPrivInfo != null)
            {
                bb.Set(suppPrivInfo);
            }
            return(GenerateKDF(securitySuite, z, bb.Array()));
        }
        public static object[][] GetData(byte[] columns, byte[] value, bool AppendAA)
        {
            List <object[]> row = new List <object[]>();

            if (columns == null || columns.Length == 0 ||
                value == null || value.Length == 0)
            {
                return(row.ToArray());
            }
            List <DataType> list = new List <DataType>();
            GXDataInfo      info = new GXDataInfo();

            info.AppendAA = AppendAA;
            GXByteBuffer bb = new GXByteBuffer();

            bb.Set(columns);
            GXCommon.SetObjectCount(value.Length, bb);
            bb.Set(value);
            object[] tmp = (object[])GXCommon.GetCompactArray(null, bb, info, false);
            row.Add((object[])tmp[0]);
            return(row.ToArray());
        }
 byte[] IGXDLMSBase.Invoke(GXDLMSSettings settings, int index, Object parameters)
 {
     //Check reply_to_HLS_authentication
     if (index == 1)
     {
         UInt32 ic = 0;
         byte[] secret;
         if (settings.Authentication == Authentication.HighGMAC)
         {
             secret = settings.SourceSystemTitle;
             GXByteBuffer bb = new GXByteBuffer(parameters as byte[]);
             bb.GetUInt8();
             ic = bb.GetUInt32();
         }
         else
         {
             secret = Secret;
         }
         byte[] serverChallenge = GXSecure.Secure(settings, settings.Cipher, ic, settings.StoCChallenge, secret);
         byte[] clientChallenge = (byte[])parameters;
         if (GXCommon.Compare(serverChallenge, clientChallenge))
         {
             if (settings.Authentication == Authentication.HighGMAC)
             {
                 secret = settings.Cipher.SystemTitle;
             }
             else
             {
                 secret = Secret;
             }
             ic = settings.Cipher.FrameCounter;
             byte[]       tmp       = GXSecure.Secure(settings, settings.Cipher, ic, settings.CtoSChallenge, secret);
             GXByteBuffer challenge = new GXByteBuffer();
             // ReturnParameters.
             challenge.SetUInt8(1);
             challenge.SetUInt8(0);
             challenge.SetUInt8((byte)DataType.OctetString);
             GXCommon.SetObjectCount(tmp.Length, challenge);
             challenge.Set(tmp);
             return(challenge.Array());
         }
         else
         {
             throw new ArgumentException("Invoke failed. Invalid attribute index.");
         }
     }
     else
     {
         throw new ArgumentException("Invoke failed. Invalid attribute index.");
     }
 }
Beispiel #32
0
        object IGXDLMSBase.GetValue(GXDLMSSettings settings, ValueEventArgs e)
        {
            GXByteBuffer bb;

            switch (e.Index)
            {
            case 1:
                return(GXCommon.LogicalNameToBytes(LogicalName));

            case 2:
                return(Token);

            case 3:
                return(Time);

            case 4:
                bb = new GXByteBuffer();
                bb.SetUInt8(DataType.Array);
                if (Descriptions == null)
                {
                    bb.SetUInt8(0);
                }
                else
                {
                    bb.SetUInt8((byte)Descriptions.Count);
                    foreach (string it in Descriptions)
                    {
                        bb.SetUInt8(DataType.OctetString);
                        bb.SetUInt8((byte)it.Length);
                        bb.Set(ASCIIEncoding.ASCII.GetBytes(it));
                    }
                }
                return(bb.Array());

            case 5:
                return(DeliveryMethod);

            case 6:
                bb = new GXByteBuffer();
                bb.SetUInt8(DataType.Structure);
                bb.SetUInt8(2);
                GXCommon.SetData(settings, bb, DataType.Enum, StatusCode);
                GXCommon.SetData(settings, bb, DataType.BitString, DataValue);
                return(bb.Array());

            default:
                e.Error = ErrorCode.ReadWriteDenied;
                break;
            }
            return(null);
        }
Beispiel #33
0
        ///<summary>
        ///Retrieves the string that indicates the level of authentication, if any.
        ///</summary>
        private static void GetAuthenticationString(GXDLMSSettings settings, GXByteBuffer data)
        {
            //If authentication is used.
            if (settings.Authentication != Authentication.None)
            {
                //Add sender ACSE-requirements field component.
                data.SetUInt8((byte)BerType.Context | (byte)PduType.SenderAcseRequirements);
                data.SetUInt8(2);
                data.SetUInt8(BerType.BitString | BerType.OctetString);
                data.SetUInt8(0x80);

                data.SetUInt8((byte)BerType.Context | (byte)PduType.MechanismName);
                //Len
                data.SetUInt8(7);
                // OBJECT IDENTIFIER
                byte[] p = { (byte)0x60, (byte)0x85, (byte)0x74, (byte)0x05, (byte)0x08, (byte)0x02, (byte)settings.Authentication };
                data.Set(p);
                //Add Calling authentication information.
                int len = 0;
                byte[] callingAuthenticationValue = null;
                if (settings.Authentication == Authentication.Low)
                {
                    if (settings.Password != null)
                    {
                        callingAuthenticationValue = settings.Password;
                        len = callingAuthenticationValue.Length;
                    }
                }
                else
                {
                    callingAuthenticationValue = settings.CtoSChallenge;
                    len = callingAuthenticationValue.Length;
                }
                //0xAC
                data.SetUInt8((byte)BerType.Context | (byte)BerType.Constructed | (byte)PduType.CallingAuthenticationValue);
                //Len
                data.SetUInt8((byte)(2 + len));
                //Add authentication information.
                data.SetUInt8((byte)BerType.Context);
                //Len.
                data.SetUInt8((byte)len);
                if (len != 0)
                {
                    data.Set(callingAuthenticationValue);
                }
            }
        }
Beispiel #34
0
 /// <summary>
 /// Code application context name.
 /// </summary>
 /// <param name="settings">DLMS settings.</param>
 /// <param name="data">Byte buffer where data is saved.</param>
 /// <param name="cipher">Is ciphering settings.</param>
 private static void GenerateApplicationContextName(GXDLMSSettings settings, GXByteBuffer data, GXICipher cipher)
 {
     //Application context name tag
     data.SetUInt8(((byte)BerType.Context | (byte)BerType.Constructed | (byte)PduType.ApplicationContextName));
     //Len
     data.SetUInt8(0x09);
     data.SetUInt8(BerType.ObjectIdentifier);
     //Len
     data.SetUInt8(0x07);
     bool ciphered = cipher != null && cipher.IsCiphered();
     if (settings.UseLogicalNameReferencing)
     {
         if (ciphered)
         {
             data.Set(GXCommon.LogicalNameObjectIdWithCiphering);
         }
         else
         {
             data.Set(GXCommon.LogicalNameObjectID);
         }
     }
     else
     {
         if (ciphered)
         {
             data.Set(GXCommon.ShortNameObjectIdWithCiphering);
         }
         else
         {
             data.Set(GXCommon.ShortNameObjectID);
         }
     }
     //Add system title if cipher or GMAC authentication is used..
     if (!settings.IsServer && (ciphered || settings.Authentication == Authentication.HighGMAC))
     {
         if (cipher.SystemTitle == null || cipher.SystemTitle.Length == 0)
         {
             throw new ArgumentNullException("SystemTitle");
         }
         //Add calling-AP-title
         data.SetUInt8(((byte)BerType.Context | (byte)BerType.Constructed | 6));
         //LEN
         data.SetUInt8((byte)(2 + cipher.SystemTitle.Length));
         data.SetUInt8((byte)BerType.OctetString);
         //LEN
         data.SetUInt8((byte)cipher.SystemTitle.Length);
         data.Set(cipher.SystemTitle);
     }
 }
Beispiel #35
0
        /// <summary>
        /// Generate User information initiate request.
        /// </summary>
        /// <param name="settings">DLMS settings.</param>
        /// <param name="cipher"></param>
        /// <param name="data"></param>
        private static void GetInitiateRequest(GXDLMSSettings settings, GXICipher cipher, GXByteBuffer data)
        {
            // Tag for xDLMS-Initiate request
            data.SetUInt8((byte)Command.InitiateRequest);
            // Usage field for dedicated-key component. Not used
            data.SetUInt8(0x00);
            //encoding of the response-allowed component (BOOLEAN DEFAULT TRUE)
            // usage flag (FALSE, default value TRUE conveyed)
            data.SetUInt8(0);

            // Usage field of the proposed-quality-of-service component. Not used
            data.SetUInt8(0x00);
            data.SetUInt8(settings.DLMSVersion);
            // Tag for conformance block
            data.SetUInt8(0x5F);
            data.SetUInt8(0x1F);
            // length of the conformance block
            data.SetUInt8(0x04);
            // encoding the number of unused bits in the bit string
            data.SetUInt8(0x00);
            if (settings.UseLogicalNameReferencing)
            {
                data.Set(settings.LnSettings.ConformanceBlock);
            }
            else
            {
                data.Set(settings.SnSettings.ConformanceBlock);
            }
            data.SetUInt16(settings.MaxPduSize);
        }
Beispiel #36
0
 /// <summary>
 /// Generate user information.
 /// </summary>
 /// <param name="settings">DLMS settings.</param>
 /// <param name="cipher"></param>
 /// <param name="data">Generated user information.</param>
 static internal void GenerateUserInformation(GXDLMSSettings settings, GXICipher cipher, GXByteBuffer encryptedData, GXByteBuffer data)
 {
     data.SetUInt8((byte)BerType.Context | (byte)BerType.Constructed | (byte)PduType.UserInformation);
     if (cipher == null || !cipher.IsCiphered())
     {
         //Length for AARQ user field
         data.SetUInt8(0x10);
         //Coding the choice for user-information (Octet STRING, universal)
         data.SetUInt8(BerType.OctetString);
         //Length
         data.SetUInt8(0x0E);
         GetInitiateRequest(settings, cipher, data);
     }
     else
     {
         if (encryptedData != null && encryptedData.Size != 0)
         {
             //Length for AARQ user field
             data.SetUInt8((byte)(4 + encryptedData.Size));
             //Tag
             data.SetUInt8(BerType.OctetString);
             data.SetUInt8((byte)(2 + encryptedData.Size));
             //Coding the choice for user-information (Octet STRING, universal)
             data.SetUInt8((byte)Command.GloInitiateRequest);
             data.SetUInt8((byte)encryptedData.Size);
             data.Set(encryptedData);
         }
         else
         {
             GXByteBuffer tmp = new GXByteBuffer();
             GetInitiateRequest(settings, cipher, tmp);
             byte[] crypted = cipher.Encrypt((byte)Command.GloInitiateRequest, cipher.SystemTitle, tmp.Array());
             //Length for AARQ user field
             data.SetUInt8((byte)(2 + crypted.Length));
             //Coding the choice for user-information (Octet STRING, universal)
             data.SetUInt8(BerType.OctetString);
             data.SetUInt8((byte)crypted.Length);
             data.Set(crypted);
         }
     }
 }
Beispiel #37
0
        /// <summary>
        /// Parse User Information from PDU.
        /// </summary>
        public static void ParseUserInformation(GXDLMSSettings settings, GXICipher cipher, GXByteBuffer data, GXDLMSTranslatorStructure xml)
        {
            byte len = data.GetUInt8();
            GXByteBuffer tmp2 = new GXByteBuffer();
            tmp2.SetUInt8(0);
            if (data.Size - data.Position < len)
            {
                throw new Exception("Not enough data.");
            }
            if (xml != null && xml.OutputType == TranslatorOutputType.StandardXml)
            {
                len = (byte)(data.Size - data.Position);
                xml.AppendLine(Command.InitiateRequest, null, GXCommon
                               .ToHex(data.Data, false, data.Position, len));
                data.Position = data.Position + len;
                return;
            }
            //Excoding the choice for user information
            int tag = data.GetUInt8();
            if (tag != 0x4)
            {
                throw new Exception("Invalid tag.");
            }
            len = data.GetUInt8();
            //Tag for xDLMS-Initate.response
            tag = data.GetUInt8();
            if (tag == (byte)Command.GloInitiateResponse)
            {
                if (xml != null)
                {
                    int cnt = GXCommon.GetObjectCount(data);
                    byte[] tmp = new byte[cnt];
                    data.Get(tmp);
                    //<glo_InitiateResponse>
                    xml.AppendLine(Command.GloInitiateResponse, "Value", GXCommon.ToHex(tmp, false));
                    return;
                }
                --data.Position;
                cipher.Security = cipher.Decrypt(settings.SourceSystemTitle, data);
                tag = data.GetUInt8();
            }
            else if (tag == (byte)Command.GloInitiateRequest)
            {
                if (xml != null)
                {
                    int cnt = GXCommon.GetObjectCount(data);
                    byte[] tmp = new byte[cnt];
                    data.Get(tmp);
                    //<glo_InitiateRequest>
                    xml.AppendLine(Command.GloInitiateRequest, "Value", GXCommon.ToHex(tmp, false));
                    return;
                }
                --data.Position;
                cipher.Security = cipher.Decrypt(settings.SourceSystemTitle, data);
                tag = data.GetUInt8();
            }
            bool response = tag == (byte)Command.InitiateResponse;
            if (response)
            {
                if (xml != null)
                {
                    //<InitiateResponse>
                    xml.AppendStartTag(Command.InitiateResponse);
                }
                //Optional usage field of the negotiated quality of service component
                tag = data.GetUInt8();
                len = 0;
                if (tag != 0)//Skip if used.
                {
                    len = data.GetUInt8();
                    data.Position += len;
                    if (len == 0 && xml != null)
                    {
                        //NegotiatedQualityOfService
                        xml.AppendLine(TranslatorGeneralTags.NegotiatedQualityOfService, "Value", "00");
                    }
                }
            }
            else if (tag == (byte)Command.InitiateRequest)
            {
                if (xml != null)
                {
                    //<InitiateRequest>
                    xml.AppendStartTag(Command.InitiateRequest);
                }
                //Optional usage field of the negotiated quality of service component
                tag = data.GetUInt8();
                //CtoS.
                if (tag != 0)
                {
                    len = data.GetUInt8();
                    settings.CtoSChallenge = new byte[len];
                    data.Get(settings.CtoSChallenge);
                }
                //Optional usage field of the negotiated quality of service component
                tag = data.GetUInt8();
                if (tag != 0)//Skip if used.
                {
                    len = data.GetUInt8();
                    data.Position += len;
                }
                //Optional usage field of the proposed quality of service component
                tag = data.GetUInt8();
                if (tag != 0)//Skip if used.
                {
                    len = data.GetUInt8();
                    data.Position += len;
                }
            }
            else
            {
                throw new Exception("Invalid tag.");
            }
            //Get DLMS version number.
            if (!response)
            {
                if (data.GetUInt8() != 6)
                {
                    throw new Exception("Invalid DLMS version number.");
                }
                //ProposedDlmsVersionNumber
                if (xml != null)
                {
                    xml.AppendLine(TranslatorGeneralTags.ProposedDlmsVersionNumber, "Value", xml.IntegerToHex(settings.DLMSVersion, 2));
                }
            }
            else
            {
                if (data.GetUInt8() != 6)
                {
                    throw new Exception("Invalid DLMS version number.");
                }
                if (xml != null)
                {
                    xml.AppendLine(TranslatorGeneralTags.NegotiatedDlmsVersionNumber, "Value", xml.IntegerToHex(settings.DLMSVersion, 2));
                }
            }

            //Tag for conformance block
            tag = data.GetUInt8();
            if (tag != 0x5F)
            {
                throw new Exception("Invalid tag.");
            }
            //Old Way...
            if (data.GetUInt8(data.Position) == 0x1F)
            {
                data.GetUInt8();
            }
            len = data.GetUInt8();
            //The number of unused bits in the bit string.
            tag = data.GetUInt8();
            if (!response)
            {
                //ProposedConformance
                if (xml != null)
                {
                    xml.AppendStartTag(TranslatorGeneralTags.ProposedConformance);
                }
                data.Get(settings.ConformanceBlock);
                tmp2.Set(settings.ConformanceBlock);
            }
            else
            {
                //NegotiatedConformance
                if (xml != null)
                {
                    xml.AppendStartTag(TranslatorGeneralTags.NegotiatedConformance);
                }
                if (settings.UseLogicalNameReferencing)
                {
                    data.Get(settings.LnSettings.ConformanceBlock);
                    tmp2.Set(settings.LnSettings.ConformanceBlock);
                }
                else
                {
                    data.Get(settings.SnSettings.ConformanceBlock);
                    tmp2.Set(settings.SnSettings.ConformanceBlock);
                }
            }
            if (xml != null)
            {
                GetConformance(tmp2.GetUInt32(), xml);
            }
            if (!response)
            {
                //Proposed max PDU size.
                settings.MaxPduSize = data.GetUInt16();
                if (xml != null)
                {
                    //ProposedConformance closing
                    xml.AppendEndTag(TranslatorGeneralTags.ProposedConformance);
                    //ProposedMaxPduSize
                    xml.AppendLine(TranslatorGeneralTags.ProposedMaxPduSize, "Value", xml.IntegerToHex(settings.MaxPduSize, 4));
                }
                //If client asks too high PDU.
                if (settings.MaxPduSize > settings.MaxServerPDUSize)
                {
                    settings.MaxPduSize = settings.MaxServerPDUSize;
                }
            }
            else
            {
                //Max PDU size.
                settings.MaxPduSize = data.GetUInt16();
                if (xml != null)
                {
                    //NegotiatedConformance closing
                    xml.AppendEndTag(TranslatorGeneralTags.NegotiatedConformance);
                    //NegotiatedMaxPduSize
                    xml.AppendLine(TranslatorGeneralTags.NegotiatedMaxPduSize, "Value", xml.IntegerToHex(settings.MaxPduSize, 4));
                }
            }
            if (response)
            {
                //VAA Name
                tag = data.GetUInt16();
                if (xml != null)
                {
                    xml.AppendLine(TranslatorGeneralTags.VaaName, "Value", xml.IntegerToHex(tag, 4));
                }
                if (tag == 0x0007)
                {
                    // If LN
                    if (!settings.UseLogicalNameReferencing)
                    {
                        throw new ArgumentException("Invalid VAA.");
                    }
                }
                else if (tag == 0xFA00)
                {
                    // If SN
                    if (settings.UseLogicalNameReferencing)
                    {
                        throw new ArgumentException("Invalid VAA.");
                    }
                }
                else
                {
                    // Unknown VAA.
                    throw new ArgumentException("Invalid VAA.");
                }
                if (xml != null)
                {
                    //<InitiateResponse>
                    xml.AppendEndTag(Command.InitiateResponse);
                }
            }
            else if (xml != null)
            {
                //</InitiateRequest>
                xml.AppendEndTag(Command.InitiateRequest);
            }
        }
Beispiel #38
0
        private static byte[] GetUserInformation(GXDLMSSettings settings, GXICipher cipher)
        {
            GXByteBuffer data = new GXByteBuffer();
            data.SetUInt8(Command.InitiateResponse); // Tag for xDLMS-Initiate response
                                                     // NegotiatedQualityOfService (not used)
            data.SetUInt8(0x1);
            data.SetUInt8(0x00);
            // DLMS Version Number
            data.SetUInt8(06);
            data.SetUInt8(0x5F);
            data.SetUInt8(0x1F);
            data.SetUInt8(0x04);// length of the conformance block
            data.SetUInt8(0x00);// encoding the number of unused bits in the bit string
            if (settings.UseLogicalNameReferencing)
            {
                data.Set(settings.LnSettings.ConformanceBlock);
            }
            else
            {
                data.Set(settings.SnSettings.ConformanceBlock);

            }
            data.SetUInt16(settings.MaxPduSize);
            //VAA Name VAA name (0x0007 for LN referencing and 0xFA00 for SN)
            if (settings.UseLogicalNameReferencing)
            {
                data.SetUInt16(0x0007);
            }
            else
            {
                data.SetUInt16(0xFA00);
            }
            if (cipher != null && cipher.IsCiphered())
            {
                return cipher.Encrypt((byte)Command.GloInitiateResponse, cipher.SystemTitle, data.Array());
            }
            return data.Array();
        }
 static internal byte[] EncryptAesGcm(AesGcmParameter param, byte[] plainText)
 {
     System.Diagnostics.Debug.WriteLine("Encrypt settings: " + param.ToString());
     param.CountTag = null;
     GXByteBuffer data = new GXByteBuffer();
     if (param.Type == CountType.Packet)
     {
         data.SetUInt8((byte)param.Security);
     }
     byte[] tmp = BitConverter.GetBytes(param.FrameCounter).Reverse().ToArray();
     byte[] aad = GetAuthenticatedData(param.Security, param.AuthenticationKey, plainText);
     GXDLMSChipperingStream gcm = new GXDLMSChipperingStream(param.Security, true, param.BlockCipherKey,
             aad, GetNonse(param.FrameCounter, param.SystemTitle), null);
     // Encrypt the secret message
     if (param.Security != Gurux.DLMS.Enums.Security.Authentication)
     {
         gcm.Write(plainText);
     }
     byte[] ciphertext = gcm.FlushFinalBlock();
     if (param.Security == Gurux.DLMS.Enums.Security.Authentication)
     {
         if (param.Type == CountType.Packet)
         {
             data.Set(tmp);
         }
         if ((param.Type & CountType.Data) != 0)
         {
             data.Set(plainText);
         }
         if ((param.Type & CountType.Tag) != 0)
         {
             param.CountTag = gcm.GetTag();
             data.Set(param.CountTag);
         }
     }
     else if (param.Security == Gurux.DLMS.Enums.Security.Encryption)
     {
         if (param.Type == CountType.Packet)
         {
             data.Set(tmp);
         }
         data.Set(ciphertext);
     }
     else if (param.Security == Gurux.DLMS.Enums.Security.AuthenticationEncryption)
     {
         if (param.Type == CountType.Packet)
         {
             data.Set(tmp);
         }
         if ((param.Type & CountType.Data) != 0)
         {
             data.Set(ciphertext);
         }
         if ((param.Type & CountType.Tag) != 0)
         {
             param.CountTag = gcm.GetTag();
             data.Set(param.CountTag);
         }
     }
     else
     {
         throw new ArgumentOutOfRangeException("security");
     }
     if (param.Type == CountType.Packet)
     {
         GXByteBuffer tmp2 = new GXByteBuffer((ushort)(10 + data.Size));
         tmp2.SetUInt8(param.Tag);
         GXCommon.SetObjectCount(data.Size, tmp2);
         tmp2.Set(data.Array());
         return tmp2.Array();
     }
     byte[] crypted = data.Array();
     System.Diagnostics.Debug.WriteLine("Crypted: " + GXCommon.ToHex(crypted, true));
     return crypted;
 }
Beispiel #40
0
 ///<summary>
 ///Convert Octet string to DLMS bytes.
 ///</summary>
 ///<param name="buff">
 ///Byte buffer where data is write.
 ///</param>
 ///<param name="value">
 ///Added value.
 ///</param>
 private static void SetOctetString(GXByteBuffer buff, object value)
 {
     // Example Logical name is octet string, so do not change to
     // string...
     if (value is string)
     {
         string[] items = ((string)value).Split('.');
         // If data is string.
         if (items.Length == 1)
         {
             byte[] tmp = ASCIIEncoding.ASCII.GetBytes((string)value);
             SetObjectCount(tmp.Length, buff);
             buff.Set(tmp);
         }
         else
         {
             SetObjectCount(items.Length, buff);
             foreach (string it in items)
             {
                 buff.SetUInt8(Convert.ToByte(it));
             }
         }
     }
     else if (value is sbyte[])
     {
         SetObjectCount(((byte[])value).Length, buff);
         buff.Set((byte[])value);
     }
     else if (value == null)
     {
         SetObjectCount(0, buff);
     }
     else
     {
         throw new Exception("Invalid data type.");
     }
 }
Beispiel #41
0
 ///<summary>
 ///Convert UTC string to DLMS bytes.
 ///</summary>
 ///<param name="buff">
 ///Byte buffer where data is write.
 ///</param>
 ///<param name="value">
 ///Added value.
 ///</param>
 private static void SetUtcString(GXByteBuffer buff, object value)
 {
     if (value != null)
     {
         byte[] tmp = ASCIIEncoding.UTF8.GetBytes(Convert.ToString(value));
         SetObjectCount(tmp.Length, buff);
         buff.Set(tmp);
     }
     else
     {
         buff.SetUInt8(0);
     }
 }
Beispiel #42
0
 ///<summary>
 ///Convert ASCII string to DLMS bytes.
 ///</summary>
 ///<param name="buff">
 ///Byte buffer where data is write.
 ///</param>
 ///<param name="value">
 ///Added value.
 ///</param>
 private static void SetString(GXByteBuffer buff, object value)
 {
     if (value != null)
     {
         string str = Convert.ToString(value);
         SetObjectCount(str.Length, buff);
         buff.Set(ASCIIEncoding.ASCII.GetBytes(str));
     }
     else
     {
         buff.SetUInt8(0);
     }
 }
Beispiel #43
0
 ///<summary>
 ///Convert Bit string to DLMS bytes.
 ///</summary>
 ///<param name="buff">
 ///Byte buffer where data is write.
 ///</param>
 ///<param name="value">
 ///Added value.
 ///</param>
 private static void SetBitString(GXByteBuffer buff, object value)
 {
     if (value is string)
     {
         GXByteBuffer tmp = new GXByteBuffer();
         byte val = 0;
         int index = 0;
         string str = ((string)value);
         SetObjectCount(str.Length, buff);
         foreach (char it in str.Reverse())
         {
             if (it == '1')
             {
                 val |= (byte)(1 << index);
                 ++index;
             }
             else if (it == '0')
             {
                 ++index;
             }
             else
             {
                 throw new Exception("Not a bit string.");
             }
             if (index == 8)
             {
                 index = 0;
                 tmp.SetUInt8(val);
                 val = 0;
             }
         }
         if (index != 0)
         {
             tmp.SetUInt8(val);
         }
         for (int pos = tmp.Size - 1; pos != -1; --pos)
         {
             buff.SetUInt8(tmp.GetUInt8(pos));
         }
     }
     else if (value is sbyte[])
     {
         byte[] arr = (byte[])value;
         SetObjectCount(arr.Length, buff);
         buff.Set(arr);
     }
     else if (value == null)
     {
         buff.SetUInt8(0);
     }
     else
     {
         throw new Exception("BitString must give as string.");
     }
 }
Beispiel #44
0
 /// <summary>
 /// Add string to byte buffer.
 /// </summary>
 /// <param name="value">String to add.</param>
 /// <param name="bb">Byte buffer where string is added.</param>
 public static void AddString(string value, GXByteBuffer bb)
 {
     bb.SetUInt8((byte)DataType.OctetString);
     if (value == null)
     {
         GXCommon.SetObjectCount(0, bb);
     }
     else
     {
         GXCommon.SetObjectCount(value.Length, bb);
         bb.Set(ASCIIEncoding.ASCII.GetBytes(value));
     }
 }
 private static byte[] GetAuthenticatedData(Gurux.DLMS.Enums.Security security, byte[] AuthenticationKey, byte[] plainText)
 {
     if (security == Gurux.DLMS.Enums.Security.Authentication)
     {
         GXByteBuffer tmp2 = new GXByteBuffer();
         tmp2.SetUInt8((byte)security);
         tmp2.Set(AuthenticationKey);
         tmp2.Set(plainText);
         return tmp2.Array();
     }
     else if (security == Gurux.DLMS.Enums.Security.Encryption)
     {
         return AuthenticationKey;
     }
     else if (security == Gurux.DLMS.Enums.Security.AuthenticationEncryption)
     {
         GXByteBuffer tmp2 = new GXByteBuffer();
         tmp2.SetUInt8((byte)security);
         tmp2.Set(AuthenticationKey);
         return tmp2.Array();
     }
     return null;
 }
Beispiel #46
0
        ///<summary>
        ///Server generates AARE message.
        ///</summary>
        internal static void GenerateAARE(GXDLMSSettings settings, GXByteBuffer data,
                                          AssociationResult result, SourceDiagnostic diagnostic, GXICipher cipher,
                                          GXByteBuffer encryptedData)
        {
            int offset = data.Size;
            // Set AARE tag and length
            data.SetUInt8(((byte)BerType.Application | (byte)BerType.Constructed | (byte)PduType.ApplicationContextName)); //0x61
                                                                                                                           // Length is updated later.
            data.SetUInt8(0);
            GenerateApplicationContextName(settings, data, cipher);
            //Result
            data.SetUInt8((byte)BerType.Context | (byte)BerType.Constructed | (byte)BerType.Integer);//0xA2
            data.SetUInt8(3); //len
            data.SetUInt8(BerType.Integer); //Tag
                                            //Choice for result (INTEGER, universal)
            data.SetUInt8(1); //Len
            data.SetUInt8((byte)result); //ResultValue
                                         //SourceDiagnostic
            data.SetUInt8(0xA3);
            data.SetUInt8(5); //len
            data.SetUInt8(0xA1); //Tag
            data.SetUInt8(3); //len
            data.SetUInt8(2); //Tag
                              //Choice for result (INTEGER, universal)
            data.SetUInt8(1); //Len
            data.SetUInt8((byte)diagnostic); //diagnostic

            //SystemTitle
            if (cipher != null && (cipher.IsCiphered() || settings.Authentication == Authentication.HighGMAC))
            {
                data.SetUInt8((byte)BerType.Context | (byte)BerType.Constructed | (byte)PduType.CalledApInvocationId);
                data.SetUInt8((byte)(2 + cipher.SystemTitle.Length));
                data.SetUInt8((byte)BerType.OctetString);
                data.SetUInt8((byte)cipher.SystemTitle.Length);
                data.Set(cipher.SystemTitle);
            }

            if (result != AssociationResult.PermanentRejected && diagnostic == SourceDiagnostic.AuthenticationRequired)
            {
                //Add server ACSE-requirenents field component.
                data.SetUInt8(0x88);
                data.SetUInt8(0x02);  //Len.
                data.SetUInt16(0x0780);
                //Add tag.
                data.SetUInt8(0x89);
                data.SetUInt8(0x07);//Len
                data.SetUInt8(0x60);
                data.SetUInt8(0x85);
                data.SetUInt8(0x74);
                data.SetUInt8(0x05);
                data.SetUInt8(0x08);
                data.SetUInt8(0x02);
                data.SetUInt8((byte)settings.Authentication);
                //Add tag.
                data.SetUInt8(0xAA);
                data.SetUInt8((byte)(2 + settings.StoCChallenge.Length));//Len
                data.SetUInt8((byte)BerType.Context);
                data.SetUInt8((byte)settings.StoCChallenge.Length);
                data.Set(settings.StoCChallenge);
            }
            byte[] tmp;
            //Add User Information
            //Tag 0xBE
            data.SetUInt8((byte)BerType.Context | (byte)BerType.Constructed | (byte)PduType.UserInformation);
            if (encryptedData != null && encryptedData.Size != 0)
            {
                GXByteBuffer tmp2 = new GXByteBuffer((UInt16)(2 + encryptedData.Size));
                tmp2.SetUInt8((byte)Command.GloInitiateResponse);
                GXCommon.SetObjectCount(encryptedData.Size, tmp2);
                tmp2.Set(encryptedData);
                tmp = tmp2.Array();
            }
            else
            {
                tmp = GetUserInformation(settings, cipher);
            }
            data.SetUInt8((byte)(2 + tmp.Length));
            //Coding the choice for user-information (Octet STRING, universal)
            data.SetUInt8(BerType.OctetString);
            //Length
            data.SetUInt8((byte)tmp.Length);
            data.Set(tmp);
            data.SetUInt8((UInt16)(offset + 1), (byte)(data.Size - offset - 2));
        }
Beispiel #47
0
        ///<summary>
        ///Convert object to DLMS bytes.
        ///</summary>
        ///<param name="settings">DLMS settings.</param>
        ///<param name="buff">Byte buffer where data is write.</param>
        ///<param name="dataType">Data type.</param>
        ///<param name="value">Added Value.</param>
        public static void SetData(GXDLMSSettings settings, GXByteBuffer buff, DataType type, object value)
        {
            if ((type == DataType.Array || type == DataType.Structure) && value is byte[])
            {
                // If byte array is added do not add type.
                buff.Set((byte[])value);
                return;
            }
            buff.SetUInt8((byte)type);
            switch (type)
            {
                case DataType.None:
                    break;
                case DataType.Boolean:
                    if (Convert.ToBoolean(value))
                    {
                        buff.SetUInt8(1);
                    }
                    else
                    {
                        buff.SetUInt8(0);
                    }
                    break;
                case DataType.Int8:
                    buff.SetUInt8((byte)Convert.ToSByte(value));
                    break;
                case DataType.UInt8:
                case DataType.Enum:
                    buff.SetUInt8(Convert.ToByte(value));
                    break;
                case DataType.Int16:
                    if (value is UInt16)
                    {
                        buff.SetUInt16((UInt16)value);
                    }
                    else
                    {
                        buff.SetUInt16((UInt16)(Convert.ToInt16(value) & 0xFFFF));
                    }
                    break;
                case DataType.UInt16:
                    buff.SetUInt16(Convert.ToUInt16(value));
                    break;
                case DataType.Int32:
                    buff.SetUInt32((UInt32)Convert.ToInt32(value));
                    break;
                case DataType.UInt32:

                    buff.SetUInt32(Convert.ToUInt32(value));
                    break;
                case DataType.Int64:
                    buff.SetUInt64((UInt64)Convert.ToInt64(value));
                    break;
                case DataType.UInt64:
                    buff.SetUInt64(Convert.ToUInt64(value));
                    break;
                case DataType.Float32:
                    buff.SetFloat((float)value);
                    break;
                case DataType.Float64:
                    buff.SetDouble((double)value);
                    break;
                case DataType.BitString:
                    SetBitString(buff, value);
                    break;
                case DataType.String:
                    SetString(buff, value);
                    break;
                case DataType.StringUTF8:
                    SetUtcString(buff, value);
                    break;
                case DataType.OctetString:
                    if (value is GXDate)
                    {
                        //Add size
                        buff.SetUInt8(5);
                        SetDate(buff, value);
                    }
                    else if (value is GXTime)
                    {
                        //Add size
                        buff.SetUInt8(4);
                        SetTime(buff, value);
                    }
                    else if (value is GXDateTime || value is DateTime)
                    {
                        //Add size
                        buff.SetUInt8(12);
                        SetDateTime(settings, buff, value);
                    }
                    else
                    {
                        SetOctetString(buff, value);
                    }
                    break;
                case DataType.Array:
                case DataType.Structure:
                    SetArray(settings, buff, value);
                    break;
                case DataType.Bcd:
                    SetBcd(buff, value);
                    break;
                case DataType.CompactArray:
                    throw new Exception("Invalid data type.");
                case DataType.DateTime:
                    SetDateTime(settings, buff, value);
                    break;
                case DataType.Date:
                    SetDate(buff, value);
                    break;
                case DataType.Time:
                    SetTime(buff, value);
                    break;
                default:
                    throw new Exception("Invalid data type.");
            }
        }
Beispiel #48
0
 Gurux.DLMS.Enums.Security GXICipher.Decrypt(byte[] title, GXByteBuffer data)
 {
     AesGcmParameter p = new AesGcmParameter(title, BlockCipherKey, AuthenticationKey);
     byte[] tmp = GXDLMSChippering.DecryptAesGcm(p, data);
     data.Clear();
     data.Set(tmp);
     return p.Security;
 }
Beispiel #49
0
 ///<summary>
 /// Chipher text.
 ///</summary>
 ///<param name="settings">
 ///DLMS settings. 
 ///</param>
 ///<param name="cipher">
 ///Cipher. 
 ///</param>
 ///<param name="ic">
 ///Invocation counter.
 ///</param>
 ///<param name="data">
 ///Text to chipher. 
 ///</param>
 ///<param name="secret">
 ///Secret. 
 ///</param>
 ///<returns>
 ///Chiphered text.
 ///</returns>
 public static byte[] Secure(GXDLMSSettings settings, GXICipher cipher, UInt32 ic, byte[] data, byte[] secret)
 {
     byte[] tmp;
     if (settings.Authentication == Authentication.High)
     {
         int len = secret.Length;
         if (len % 16 != 0)
         {
             len += 16 - (secret.Length % 16);
         }
         byte[] p = new byte[len];
         byte[] s = new byte[16];
         byte[] x = new byte[16];
         int i;
         data.CopyTo(p, 0);
         secret.CopyTo(s, 0);
         for (i = 0; i < p.Length; i += 16)
         {
             Buffer.BlockCopy(p, i, x, 0, 16);
             GXAes128.Encrypt(x, s);
             Buffer.BlockCopy(x, 0, p, i, 16);
         }
         Buffer.BlockCopy(p, 0, x, 0, 16);
         return x;
     }
     // Get server Challenge.
     GXByteBuffer challenge = new GXByteBuffer();
     // Get shared secret
     if (settings.Authentication == Authentication.HighGMAC)
     {
         challenge.Set(data);              
     }
     else
     {
         challenge.Set(data);
         challenge.Set(secret);
     }
     tmp = challenge.Array();
     if (settings.Authentication == Authentication.HighMD5)
     {
         using (MD5 md5Hash = MD5.Create())
         {
             tmp = md5Hash.ComputeHash(tmp);
             return tmp;
         }
     }
     else if (settings.Authentication == Authentication.HighSHA1)
     {
         using (SHA1 sha = new SHA1CryptoServiceProvider())
         {
             tmp = sha.ComputeHash(tmp);
             return tmp;
         }
     }
     else if (settings.Authentication == Authentication.HighGMAC)
     {
         //SC is always Security.Authentication.
         AesGcmParameter p = new AesGcmParameter(0, Security.Authentication, ic,
             secret, cipher.BlockCipherKey, cipher.AuthenticationKey);
         p.Type = CountType.Tag;
         challenge.Clear();
         challenge.SetUInt8((byte)Security.Authentication);
         challenge.SetUInt32(p.FrameCounter);
         challenge.Set(GXDLMSChippering.EncryptAesGcm(p, tmp));
         tmp = challenge.Array();
         return tmp;
     }
     return data;
 }