Пример #1
0
        /// <summary>
        /// Reserved for internal use.
        /// </summary>
        /// <param name="buff"></param>
        /// <param name="index"></param>
        internal void EncodeData(byte[] buff, ref int index)
        {
            int tag = buff[index++];

            if (tag != 0xA1)
            {
                throw new Exception("Invalid tag.");
            }
            //Get length.
            int len = buff[index++];

            if (buff.Length - index < len)
            {
                throw new Exception("Encoding failed. Not enough data.");
            }
            if (buff[index++] != 0x6)
            {
                throw new Exception("Encoding failed. Not an Object ID.");
            }
            //Object ID length.
            len = buff[index++];
            //Compare Object ID to check is Logical name used.
            UseLN = GXCommon.Compare(buff, ref index, GXCommon.LogicalNameObjectID);
            if (!UseLN)
            {
                index += GXCommon.ShortNameObjectID.Length;
            }
        }
Пример #2
0
 public override bool Equals(object obj)
 {
     if (obj is GXPrivateKey pk)
     {
         return(GXCommon.Compare(RawValue, pk.RawValue));
     }
     return(false);
 }
Пример #3
0
 public override bool Equals(object obj)
 {
     if (obj is GXPublicKey o)
     {
         return(GXCommon.Compare(RawValue, o.RawValue));
     }
     return(false);
 }
Пример #4
0
        /// <summary>
        /// Decrypt data using AES RFC3394.
        /// </summary>
        /// <param name="input">Decrypted data.</param>
        internal byte[] DecryptAes(byte[] input)
        {
            int n = input.Length / 8;

            if ((n * 8) != input.Length)
            {
                throw new ArgumentOutOfRangeException("Invalid data.");
            }

            byte[] iv = { 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6 };
            byte[] block;
            if (input.Length > iv.Length)
            {
                block = new byte[input.Length - iv.Length];
            }
            else
            {
                block = new byte[iv.Length];
            }
            byte[] a   = new byte[iv.Length];
            byte[] buf = new byte[8 + iv.Length];

            Array.Copy(input, 0, a, 0, iv.Length);
            Array.Copy(input, 0 + iv.Length, block, 0, input.Length - iv.Length);

            n = n - 1;
            if (n == 0)
            {
                n = 1;
            }

            for (int j = 5; j >= 0; j--)
            {
                for (int i = n; i >= 1; i--)
                {
                    Array.Copy(a, 0, buf, 0, iv.Length);
                    Array.Copy(block, 8 * (i - 1), buf, iv.Length, 8);

                    int t = n * j + i;
                    for (int k = 1; t != 0; k++)
                    {
                        byte v = (byte)t;

                        buf[iv.Length - k] ^= v;
                        t = (int)((uint)t >> 8);
                    }

                    ProcessBlock(buf, 0, buf, 0);
                    Array.Copy(buf, 0, a, 0, 8);
                    Array.Copy(buf, 8, block, 8 * (i - 1), 8);
                }
            }
            if (!GXCommon.Compare(a, iv))
            {
                throw new ArithmeticException("Invalid CRC");
            }
            return(block);
        }
 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.");
     }
 }
Пример #6
0
 byte[] IGXDLMSBase.Invoke(GXDLMSSettings settings, ValueEventArgs e)
 {
     //Check reply_to_HLS_authentication
     if (e.Index == 8)
     {
         UInt32 ic = 0;
         byte[] secret;
         if (settings.Authentication == Authentication.HighGMAC)
         {
             secret = settings.SourceSystemTitle;
             GXByteBuffer bb = new GXByteBuffer(e.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[])e.Parameters;
         if (GXCommon.Compare(serverChallenge, clientChallenge))
         {
             if (settings.Authentication == Authentication.HighGMAC)
             {
                 secret = settings.Cipher.SystemTitle;
                 ic     = settings.Cipher.InvocationCounter;
             }
             else
             {
                 secret = Secret;
             }
             settings.Connected = true;
             return(GXSecure.Secure(settings, settings.Cipher, ic, settings.CtoSChallenge, secret));
         }
         else
         {
             // If the password does not match.
             settings.Connected = false;
             return(null);
         }
     }
     else
     {
         e.Error = ErrorCode.ReadWriteDenied;
         return(null);
     }
 }
Пример #7
0
 byte[][] IGXDLMSBase.Invoke(object sender, int index, Object parameters)
 {
     //Check reply_to_HLS_authentication
     if (index == 8)
     {
         GXDLMSServerBase s = sender as GXDLMSServerBase;
         if (s == null)
         {
             throw new ArgumentException("sender");
         }
         GXDLMS b = s.m_Base;
         //Get server Challenge.
         List <byte> challenge = null;
         List <byte> CtoS      = null;
         //Find shared secret
         foreach (GXAuthentication it in s.Authentications)
         {
             if (it.Type == b.Authentication)
             {
                 CtoS      = new List <byte>(it.SharedSecret);
                 challenge = new List <byte>(it.SharedSecret);
                 challenge.AddRange(b.StoCChallenge);
                 break;
             }
         }
         byte[] serverChallenge = GXDLMS.Chipher(b.Authentication, challenge.ToArray(), null);
         byte[] clientChallenge = (byte[])parameters;
         int    pos             = 0;
         if (GXCommon.Compare(clientChallenge, ref pos, serverChallenge))
         {
             CtoS.AddRange(b.CtoSChallenge);
             return(s.Acknowledge(Command.WriteResponse, 0, GXDLMS.Chipher(b.Authentication, CtoS.ToArray(), null), DataType.OctetString));
         }
         else
         {
             //Return HW error.
             return(s.ServerReportError(Command.MethodRequest, 1));
         }
     }
     else
     {
         throw new ArgumentException("Invoke failed. Invalid attribute index.");
     }
 }
Пример #8
0
 byte[] IGXDLMSBase.Invoke(GXDLMSSettings settings, ValueEventArgs e)
 {
     //Check reply_to_HLS_authentication
     if (e.Index == 1)
     {
         UInt32 ic = 0;
         byte[] secret;
         if (settings.Authentication == Authentication.HighGMAC)
         {
             secret = settings.SourceSystemTitle;
             GXByteBuffer bb = new GXByteBuffer(e.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[])e.Parameters;
         if (serverChallenge != null && clientChallenge != null && GXCommon.Compare(serverChallenge, clientChallenge))
         {
             if (settings.Authentication == Authentication.HighGMAC)
             {
                 secret = settings.Cipher.SystemTitle;
                 ic     = settings.Cipher.InvocationCounter;
             }
             else
             {
                 secret = Secret;
             }
             AssociationStatus = AssociationStatus.Associated;
             return(GXSecure.Secure(settings, settings.Cipher, ic, settings.CtoSChallenge, secret));
         }
         else //If the password does not match.
         {
             AssociationStatus = AssociationStatus.NonAssociated;
             return(null);
         }
     }
     else if (e.Index == 2)
     {
         byte[] tmp = e.Parameters as byte[];
         if (tmp == null || tmp.Length == 0)
         {
             e.Error = ErrorCode.ReadWriteDenied;
         }
         else
         {
             Secret = tmp;
         }
     }
     else if (e.Index == 3)
     {
         //Add COSEM object.
         GXDLMSObject obj = GetObject(settings, e.Parameters as object[]);
         //Unknown objects are not add.
         if (obj is IGXDLMSBase)
         {
             if (ObjectList.FindByLN(obj.ObjectType, obj.LogicalName) == null)
             {
                 ObjectList.Add(obj);
             }
             if (settings.Objects.FindByLN(obj.ObjectType, obj.LogicalName) == null)
             {
                 settings.Objects.Add(obj);
             }
         }
     }
     else if (e.Index == 4)
     {
         //Remove COSEM object.
         GXDLMSObject obj = GetObject(settings, e.Parameters as object[]);
         //Unknown objects are not removed.
         if (obj is IGXDLMSBase)
         {
             GXDLMSObject t = ObjectList.FindByLN(obj.ObjectType, obj.LogicalName);
             if (t != null)
             {
                 ObjectList.Remove(t);
             }
             //Item is not removed from all objects. It might be that use wants remove object only from association view.
         }
     }
     else if (e.Index == 5)
     {
         object[] tmp = e.Parameters as object[];
         if (tmp == null || tmp.Length != 2)
         {
             e.Error = ErrorCode.ReadWriteDenied;
         }
         else
         {
             UserList.Add(new KeyValuePair <byte, string>(Convert.ToByte(tmp[0]), Convert.ToString(tmp[1])));
         }
     }
     else if (e.Index == 6)
     {
         object[] tmp = e.Parameters as object[];
         if (tmp == null || tmp.Length != 2)
         {
             e.Error = ErrorCode.ReadWriteDenied;
         }
         else
         {
             UserList.Remove(new KeyValuePair <byte, string>(Convert.ToByte(tmp[0]), Convert.ToString(tmp[1])));
         }
     }
     else
     {
         e.Error = ErrorCode.ReadWriteDenied;
     }
     return(null);
 }
Пример #9
0
        /// <summary>
        /// Ask Gurux certificate server to generate the new certificate.
        /// </summary>
        /// <param name="address">Certificate server address.</param>
        /// <param name="certifications">List of certification types and PKCS #10 certificates.</param>
        /// <returns>Generated certificate(s).</returns>
        public static GXx509Certificate[] GetCertificate(string address, List <KeyValuePair <CertificateType, GXPkcs10> > certifications)
        {
            StringBuilder usage = new StringBuilder();

            foreach (KeyValuePair <CertificateType, GXPkcs10> it in certifications)
            {
                if (usage.Length != 0)
                {
                    usage.Append(", ");
                }
                usage.Append("{\"KeyUsage\":");
                switch (it.Key)
                {
                case CertificateType.DigitalSignature:
                    usage.Append(Convert.ToString((int)KeyUsage.DigitalSignature));
                    break;

                case CertificateType.KeyAgreement:
                    usage.Append(Convert.ToString((int)KeyUsage.KeyAgreement));
                    break;

                default:
                    throw new Exception("Invalid type.");
                }
                usage.Append(", \"CSR\":\"");
                usage.Append(it.Value.ToDer());
                usage.Append("\"}");
            }
            HttpWebRequest request = HttpWebRequest.Create(address) as HttpWebRequest;
            string         der     = "{\"Certificates\":[" + usage.ToString() + "]}";

            request.ContentType = "application/json";
            request.Method      = "POST";
            using (var streamWriter = new StreamWriter(request.GetRequestStream()))
            {
                streamWriter.Write(der);
                streamWriter.Flush();
                streamWriter.Close();
            }
            try
            {
                using (HttpWebResponse webresponse = request.GetResponse() as HttpWebResponse)
                {
                    using (StreamReader reader = new StreamReader(webresponse.GetResponseStream()))
                    {
                        string str = reader.ReadToEnd();
                        int    pos = str.IndexOf("[");
                        if (pos == -1)
                        {
                            throw new Exception("Certificates are missing.");
                        }
                        str = str.Substring(pos + 2);
                        pos = str.IndexOf("]");
                        if (pos == -1)
                        {
                            throw new Exception("Certificates are missing.");
                        }
                        str = str.Substring(0, pos - 1);
                        List <GXx509Certificate> list = new List <GXx509Certificate>();
                        string[] tmp = str.Split(new string[] { "\"", "," }, StringSplitOptions.RemoveEmptyEntries);
                        pos = 0;
                        foreach (string it in tmp)
                        {
                            GXx509Certificate x509 = GXx509Certificate.FromDer(it);
                            if (!GXCommon.Compare(certifications[pos].Value.PublicKey.RawValue, x509.PublicKey.RawValue))
                            {
                                throw new Exception("Create certificate signingRequest generated wrong public key.");
                            }
                            ++pos;
                            list.Add(x509);
                        }
                        return(list.ToArray());
                    }
                }
            }
            catch (WebException ex)
            {
                throw new Exception(new StreamReader(ex.Response.GetResponseStream()).ReadToEnd());
            }
        }
Пример #10
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);
        }
Пример #11
0
 byte[] IGXDLMSBase.Invoke(GXDLMSSettings settings, ValueEventArgs e)
 {
     //Check reply_to_HLS_authentication
     if (e.Index == 1)
     {
         UInt32 ic = 0;
         byte[] secret;
         if (settings.Authentication == Authentication.HighGMAC)
         {
             secret = settings.SourceSystemTitle;
             GXByteBuffer bb = new GXByteBuffer(e.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[])e.Parameters;
         if (serverChallenge != null && clientChallenge != null && GXCommon.Compare(serverChallenge, clientChallenge))
         {
             if (settings.Authentication == Authentication.HighGMAC)
             {
                 secret = settings.Cipher.SystemTitle;
                 ic     = settings.Cipher.InvocationCounter;
             }
             else
             {
                 secret = Secret;
             }
             settings.Connected = true;
             return(GXSecure.Secure(settings, settings.Cipher, ic, settings.CtoSChallenge, secret));
         }
         else //If the password does not match.
         {
             settings.Connected = false;
             return(null);
         }
     }
     else if (e.Index == 2)
     {
         byte[] tmp = e.Parameters as byte[];
         if (tmp == null || tmp.Length == 0)
         {
             e.Error = ErrorCode.ReadWriteDenied;
         }
         else
         {
             Secret = tmp;
         }
     }
     else if (e.Index == 5)
     {
         object[] tmp = e.Parameters as object[];
         if (tmp == null || tmp.Length != 2)
         {
             e.Error = ErrorCode.ReadWriteDenied;
         }
         else
         {
             UserList.Add(new KeyValuePair <byte, string>(Convert.ToByte(tmp[0]), Convert.ToString(tmp[1])));
         }
     }
     else if (e.Index == 6)
     {
         object[] tmp = e.Parameters as object[];
         if (tmp == null || tmp.Length != 2)
         {
             e.Error = ErrorCode.ReadWriteDenied;
         }
         else
         {
             UserList.Remove(new KeyValuePair <byte, string>(Convert.ToByte(tmp[0]), Convert.ToString(tmp[1])));
         }
     }
     else
     {
         e.Error = ErrorCode.ReadWriteDenied;
     }
     return(null);
 }