Exemplo n.º 1
0
 internal static byte[] Decrypt(AesGcmParameter p, GXByteBuffer data)
 {
     byte[] tmp = GXDLMSChippering.DecryptAesGcm(p, data);
     data.Clear();
     data.Set(tmp);
     return(tmp);
 }
Exemplo n.º 2
0
 internal static byte[] Encrypt(AesGcmParameter p, byte[] data)
 {
     if (p.Security != Security.None)
     {
         return(GXDLMSChippering.EncryptAesGcm(p, data));
     }
     return(data);
 }
Exemplo n.º 3
0
 internal static byte[] Encrypt(AesGcmParameter p, byte[] data)
 {
     if (p.Security != Gurux.DLMS.Enums.Security.None)
     {
         byte[] tmp = GXDLMSChippering.EncryptAesGcm(p, data);
         return(tmp);
     }
     return(data);
 }
Exemplo n.º 4
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);
        }
Exemplo n.º 5
0
 byte[] GXICipher.Encrypt(byte tag, byte[] title, byte[] data)
 {
     if (Security != Security.None)
     {
         AesGcmParameter p = new AesGcmParameter(tag, Security, FrameCounter,
                                                 title, BlockCipherKey, AuthenticationKey);
         byte[] tmp = GXDLMSChippering.EncryptAesGcm(p, data);
         ++FrameCounter;
         return(tmp);
     }
     return(data);
 }
Exemplo n.º 6
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());
        }
Exemplo n.º 7
0
 private static byte[] GetAuthenticatedData(AesGcmParameter p, byte[] plainText)
 {
     if (p.Security == (byte)Security.Authentication)
     {
         GXByteBuffer tmp2 = new GXByteBuffer();
         tmp2.SetUInt8((byte)p.Security);
         tmp2.Set(p.AuthenticationKey);
         tmp2.Set(plainText);
         return(tmp2.Array());
     }
     else if (p.Security == (byte)Security.Encryption)
     {
         return(p.AuthenticationKey);
     }
     else if (p.Security == (byte)Security.AuthenticationEncryption)
     {
         GXByteBuffer tmp2 = new GXByteBuffer();
         tmp2.SetUInt8((byte)p.Security);
         tmp2.Set(p.AuthenticationKey);
         return(tmp2.Array());
     }
     return(null);
 }
Exemplo n.º 8
0
        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((UInt32)param.InvocationCounter).Reverse().ToArray();
            byte[] aad = GetAuthenticatedData(param, plainText);
            GXDLMSChipperingStream gcm = new GXDLMSChipperingStream(param.Security, true, param.BlockCipherKey,
                                                                    aad, GetNonse((UInt32)param.InvocationCounter, param.SystemTitle), null);

            // Encrypt the secret message
            if (param.Security != (byte)Security.Authentication)
            {
                gcm.Write(plainText);
            }
            byte[] ciphertext = gcm.FlushFinalBlock();
            if (param.Security == (byte)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 == (byte)Security.Encryption)
            {
                if (param.Type == CountType.Packet)
                {
                    data.Set(tmp);
                }
                data.Set(ciphertext);
            }
            else if (param.Security == (byte)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);
                if (param.Tag == (int)Command.GeneralGloCiphering ||
                    param.Tag == (int)Command.GeneralDedCiphering ||
                    param.Tag == (int)Command.DataNotification)
                {
                    if (!param.IgnoreSystemTitle)
                    {
                        GXCommon.SetObjectCount(param.SystemTitle.Length, tmp2);
                        tmp2.Set(param.SystemTitle);
                    }
                    else
                    {
                        tmp2.SetUInt8(0);
                    }
                }
                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);
        }
Exemplo n.º 9
0
        /// <summary>
        /// Decrypt data.
        /// </summary>
        /// <param name="p">Decryption parameters</param>
        /// <returns>Decrypted data.</returns>
        public static byte[] DecryptAesGcm(AesGcmParameter p, GXByteBuffer data)
        {
            if (data == null || data.Size < 2)
            {
                throw new ArgumentOutOfRangeException("cryptedData");
            }
            byte[]  tmp;
            int     len;
            Command cmd = (Command)data.GetUInt8();

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

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

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

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

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

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

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

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

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

            gcm.Write(ciphertext);
            if (transactionId != 0)
            {
                p.InvocationCounter = transactionId;
            }
            return(gcm.FlushFinalBlock());
        }
Exemplo n.º 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:
                len = GXCommon.GetObjectCount(data);
                if (len != 0)
                {
                    p.SystemTitle = new byte[len];
                    data.Get(p.SystemTitle);
                }
                break;

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

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

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

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

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

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

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

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

            /*
             * len = Gurux.DLMS.Internal.GXCommon.GetObjectCount(data);
             * p.Security = (Gurux.DLMS.Enums.Security)data.GetUInt8();
             * p.InvocationCounter = data.GetUInt32();
             * System.Diagnostics.Debug.WriteLine("Decrypt settings: " + p.ToString());
             * System.Diagnostics.Debug.WriteLine("Encrypted: " + GXCommon.ToHex(data.Array(), true));
             *
             * byte[] tag = new byte[12];
             * byte[] encryptedData;
             * int length;
             * if (p.Security == Gurux.DLMS.Enums.Security.Authentication)
             * {
             *  length = data.Size - data.Position - 12;
             *  encryptedData = new byte[length];
             *  data.Get(encryptedData);
             *  data.Get(tag);
             *  // Check tag.
             *  EncryptAesGcm(p, encryptedData);
             *  if (!GXDLMSChipperingStream.TagsEquals(tag, p.CountTag))
             *  {
             *      throw new GXDLMSException("Decrypt failed. Invalid tag.");
             *  }
             *  return encryptedData;
             * }
             * byte[] ciphertext = null;
             * if (p.Security == Gurux.DLMS.Enums.Security.Encryption)
             * {
             *  length = data.Size - data.Position;
             *  ciphertext = new byte[length];
             *  data.Get(ciphertext);
             * }
             * else if (p.Security == Gurux.DLMS.Enums.Security.AuthenticationEncryption)
             * {
             *  length = data.Size - data.Position - 12;
             *  ciphertext = new byte[length];
             *  data.Get(ciphertext);
             *  data.Get(tag);
             * }
             * byte[] aad = GetAuthenticatedData(p.Security, p.AuthenticationKey, ciphertext);
             * byte[] iv = GetNonse(p.InvocationCounter, p.SystemTitle);
             * GXDLMSChipperingStream gcm = new GXDLMSChipperingStream(p.Security, true, p.BlockCipherKey, aad, iv, tag);
             * gcm.Write(ciphertext);
             * ciphertext = gcm.FlushFinalBlock();
             * if (p.Security == Gurux.DLMS.Enums.Security.AuthenticationEncryption)
             * {
             *  // Check tag.
             *  EncryptAesGcm(p, ciphertext);
             *  if (!GXDLMSChipperingStream.TagsEquals(tag, p.CountTag))
             *  {
             *      //    throw new GXDLMSException("Decrypt failed. Invalid tag.");
             *  }
             * }
             * return ciphertext;
             */
        }
Exemplo n.º 11
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, uint 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)
            {
#if !WINDOWS_UWP
                using (MD5 md5Hash = MD5.Create())
                {
                    tmp = md5Hash.ComputeHash(tmp);
                    return(tmp);
                }
#endif
            }
            else if (settings.Authentication == Authentication.HighSHA1)
            {
#if !WINDOWS_UWP
                using (SHA1 sha = new SHA1CryptoServiceProvider())
                {
                    tmp = sha.ComputeHash(tmp);
                    return(tmp);
                }
#endif
            }
            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.InvocationCounter);
                challenge.Set(GXDLMSChippering.EncryptAesGcm(p, tmp));
                tmp = challenge.Array();
                return(tmp);
            }
            return(data);
        }
Exemplo n.º 12
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>
        internal 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 ||
                settings.Authentication == Authentication.HighECDSA)
            {
                challenge.Set(data);
            }
            else if (settings.Authentication == Authentication.HighSHA256)
            {
                challenge.Set(secret);
            }
            else
            {
                challenge.Set(data);
                challenge.Set(secret);
            }
            tmp = challenge.Array();
            if (settings.Authentication == Authentication.HighMD5)
            {
#if !WINDOWS_UWP
                using (MD5 md5Hash = MD5.Create())
                {
                    tmp = md5Hash.ComputeHash(tmp);
                    return(tmp);
                }
#endif
            }
            else if (settings.Authentication == Authentication.HighSHA1)
            {
#if !WINDOWS_UWP
                using (SHA1 sha = new SHA1CryptoServiceProvider())
                {
                    tmp = sha.ComputeHash(tmp);
                    return(tmp);
                }
#endif
            }
            else if (settings.Authentication == Authentication.HighSHA256)
            {
                //Windows UWP, IOS ad Android don't support this.
#if !WINDOWS_UWP && !__IOS__ && !__ANDROID__
                using (SHA256 sha = new SHA256CryptoServiceProvider())
                {
                    tmp = sha.ComputeHash(tmp);
                    return(tmp);
                }
#endif
            }
            else if (settings.Authentication == Authentication.HighGMAC)
            {
                //SC is always Security.Authentication.
                AesGcmParameter p = new AesGcmParameter(0, Security.Authentication,
                                                        cipher.SecuritySuite,
                                                        ic,
                                                        secret,
                                                        cipher.BlockCipherKey,
                                                        cipher.AuthenticationKey);
                p.Type = CountType.Tag;
                challenge.Clear();
                //Security suite is 0.
                challenge.SetUInt8((byte)Security.Authentication);
                challenge.SetUInt32((UInt32)p.InvocationCounter);
                challenge.Set(GXDLMSChippering.EncryptAesGcm(p, tmp));
                tmp = challenge.Array();
                return(tmp);
            }
            else if (settings.Authentication == Authentication.HighECDSA)
            {
                if (cipher.SigningKeyPair.Key == null)
                {
                    throw new ArgumentNullException("SigningKeyPair is not set.");
                }
                GXEcdsa      sig = new GXEcdsa(cipher.SigningKeyPair.Key);
                GXByteBuffer bb  = new GXByteBuffer();
                bb.Set(settings.Cipher.SystemTitle);
                bb.Set(settings.SourceSystemTitle);
                if (settings.IsServer)
                {
                    bb.Set(settings.CtoSChallenge);
                    bb.Set(settings.StoCChallenge);
                }
                else
                {
                    bb.Set(settings.StoCChallenge);
                    bb.Set(settings.CtoSChallenge);
                }
                data = sig.Sign(bb.Array());
            }
            return(data);
        }
Exemplo n.º 13
0
        /// <summary>
        /// Decrypt data.
        /// </summary>
        /// <param name="p">Decryption parameters</param>
        /// <returns>Decrypted data.</returns>
        public static byte[] DecryptAesGcm(AesGcmParameter p, GXByteBuffer data)
        {
            if (data == null || data.Size < 2)
            {
                throw new ArgumentOutOfRangeException("cryptedData");
            }
            int     len;
            Command cmd = (Command)data.GetUInt8();

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

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

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

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

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

            gcm.Write(ciphertext);
            ciphertext = gcm.FlushFinalBlock();
            if (p.Security == Gurux.DLMS.Enums.Security.AuthenticationEncryption)
            {
                // Check tag.
                EncryptAesGcm(p, ciphertext);
                if (!GXDLMSChipperingStream.TagsEquals(tag, p.CountTag))
                {
                    //    throw new GXDLMSException("Decrypt failed. Invalid tag.");
                }
            }
            return(ciphertext);
        }
Exemplo n.º 14
0
 byte[] GXICipher.Encrypt(byte tag, byte[] title, byte[] data)
 {
     if (Security != Gurux.DLMS.Enums.Security.None)
     {
         AesGcmParameter p = new AesGcmParameter(tag, Security, FrameCounter,
                                                 title, BlockCipherKey, AuthenticationKey);
         byte[] tmp = GXDLMSChippering.EncryptAesGcm(p, data);
         ++FrameCounter;
         return tmp;
     }
     return data;
 }
Exemplo n.º 15
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;
 }
Exemplo n.º 16
0
 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;
 }
Exemplo n.º 17
0
        /// <summary>
        /// Decrypt data.
        /// </summary>
        /// <param name="p">Decryption parameters</param>
        /// <returns>Decrypted data.</returns>
        public static byte[] DecryptAesGcm(AesGcmParameter p, GXByteBuffer data)
        {
            if (data == null || data.Size < 2)
            {
                throw new ArgumentOutOfRangeException("cryptedData");
            }
            int len;
            Command cmd = (Command)data.GetUInt8();
            switch (cmd)
            {
                case Command.GloGeneralCiphering:
                    len = GXCommon.GetObjectCount(data);
                    p.SystemTitle = new byte[len];
                    data.Get(p.SystemTitle);
                    break;
                case Command.GloInitiateRequest:
                case Command.GloInitiateResponse:
                case Command.GloReadRequest:
                case Command.GloReadResponse:
                case Command.GloWriteRequest:
                case Command.GloWriteResponse:
                case Command.GloGetRequest:
                case Command.GloGetResponse:
                case Command.GloSetRequest:
                case Command.GloSetResponse:
                case Command.GloMethodRequest:
                case Command.GloMethodResponse:
                case Command.GloEventNotificationRequest:
                    break;
                default:
                    throw new ArgumentOutOfRangeException("cryptedData");
            }
            len = Gurux.DLMS.Internal.GXCommon.GetObjectCount(data);
            p.Security = (Gurux.DLMS.Enums.Security)data.GetUInt8();
            p.FrameCounter = data.GetUInt32();
            System.Diagnostics.Debug.WriteLine("Decrypt settings: " + p.ToString());
            System.Diagnostics.Debug.WriteLine("Encrypted: " + GXCommon.ToHex(data.Array(), true));

            byte[] tag = new byte[12];
            byte[] encryptedData;
            int length;
            if (p.Security == Gurux.DLMS.Enums.Security.Authentication)
            {
                length = data.Size - data.Position - 12;
                encryptedData = new byte[length];
                data.Get(encryptedData);
                data.Get(tag);
                // Check tag.
                EncryptAesGcm(p, encryptedData);
                if (!GXDLMSChipperingStream.TagsEquals(tag, p.CountTag))
                {
                    throw new GXDLMSException("Decrypt failed. Invalid tag.");
                }
                return encryptedData;
            }
            byte[] ciphertext = null;
            if (p.Security == Gurux.DLMS.Enums.Security.Encryption)
            {
                length = data.Size - data.Position;
                ciphertext = new byte[length];
                data.Get(ciphertext);
            }
            else if (p.Security == Gurux.DLMS.Enums.Security.AuthenticationEncryption)
            {
                length = data.Size - data.Position - 12;
                ciphertext = new byte[length];
                data.Get(ciphertext);
                data.Get(tag);
            }
            byte[] aad = GetAuthenticatedData(p.Security, p.AuthenticationKey, data.Array());
            byte[] iv = GetNonse(p.FrameCounter, p.SystemTitle);
            GXDLMSChipperingStream gcm = new GXDLMSChipperingStream(p.Security, true, p.BlockCipherKey, aad, iv, tag);
            gcm.Write(ciphertext);
            return gcm.FlushFinalBlock();
        }
Exemplo n.º 18
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);
        }
Exemplo n.º 19
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;
 }
Exemplo n.º 20
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");
            }
            Command cmd = (Command)data.GetUInt8();

            if (!((byte)cmd == 0x21 || (byte)cmd == 0x28 ||
                  cmd == Command.GloGetRequest ||
                  cmd == Command.GloGetResponse ||
                  cmd == Command.GloSetRequest ||
                  cmd == Command.GloSetResponse ||
                  cmd == Command.GloMethodRequest ||
                  cmd == Command.GloMethodResponse))
            {
                throw new ArgumentOutOfRangeException("cryptedData");
            }
            int len = Gurux.DLMS.Internal.GXCommon.GetObjectCount(data);

            p.Security     = (Security)data.GetUInt8();
            p.FrameCounter = data.GetUInt32();
            System.Diagnostics.Debug.WriteLine("Decrypt settings: " + p.ToString());
            System.Diagnostics.Debug.WriteLine("Encrypted: " + GXCommon.ToHex(data.Array(), true));

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

            if (p.Security == Security.Authentication)
            {
                length        = data.Size - data.Position - 12;
                encryptedData = new byte[length];
                data.Get(encryptedData);
                data.Get(tag);
                // Check tag.
                EncryptAesGcm(p, encryptedData);
                if (!GXDLMSChipperingStream.TagsEquals(tag, p.CountTag))
                {
                    throw new GXDLMSException("Decrypt failed. Invalid tag.");
                }
                return(encryptedData);
            }
            byte[] ciphertext = null;
            if (p.Security == 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.Security, p.AuthenticationKey, data.Array());
            GXDLMSChipperingStream gcm = new GXDLMSChipperingStream(p.Security, false, p.BlockCipherKey, aad, GetNonse(p.FrameCounter, p.SystemTitle), tag);

            gcm.Write(ciphertext);
            return(gcm.FlushFinalBlock());
        }