public void OnValueChanged(GXDLMSViewArguments arg) { if (arg.Index == 2) { if (arg.Value is byte[] && (arg.Value as byte[]).Length == 6) { GXBitString bs = new GXBitString(GXBitString.ToBitString((byte[])arg.Value, 0, 16)); int val = Convert.ToUInt16(bs); ValuesLb.ItemCheck -= ValuesLb_ItemCheck; for (int pos = 0; pos != 16; ++pos) { ValuesLb.SetItemChecked(pos, bs.Value[pos] == '1'); } ValuesLb.ItemCheck += ValuesLb_ItemCheck; GXByteBuffer bb = new GXByteBuffer((byte[])arg.Value); bb.Position = 2; DurationTb.Text = bb.GetUInt32().ToString(); HexTb.Text = bb.ToString(); } else { DurationTb.Text = HexTb.Text = ""; ValuesLb.ItemCheck -= ValuesLb_ItemCheck; for (int pos = 0; pos != 16; ++pos) { ValuesLb.SetItemChecked(pos, false); } ValuesLb.ItemCheck += ValuesLb_ItemCheck; } } else { throw new IndexOutOfRangeException("index"); } }
/// <summary> /// Get values from byte buffer. /// </summary> /// <param name="value"></param> private void FromByteBuffer(GXByteBuffer value) { for (int pos = value.Size - 4; pos > -1; pos = pos - 4) { Add(value.GetUInt32(pos)); } switch (value.Size % 4) { case 1: Add(value.GetUInt8()); break; case 2: Add(value.GetUInt16()); break; case 3: // Data.Add(value.GetUInt24()); break; default: break; } changed = true; }
private static UInt32 FromAddressString(string value) { if (string.IsNullOrEmpty(value)) { return(0); } GXByteBuffer bb = new GXByteBuffer(System.Net.IPAddress.Parse(value).GetAddressBytes()); return(bb.GetUInt32()); }
private static UInt32 FromAddressString(IPAddress value) { if (value == null) { return(0); } GXByteBuffer bb = new GXByteBuffer(value.GetAddressBytes()); return(bb.GetUInt32()); }
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."); } }
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); } }
/// <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()); }
/// <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; */ }
void IGXDLMSBase.SetValue(GXDLMSSettings settings, ValueEventArgs e) { if (e.Index == 1) { LogicalName = GXCommon.ToLogicalName(e.Value); } else if (e.Index == 2) { ObjectList.Clear(); if (e.Value != null) { foreach (Object[] item in (Object[])e.Value) { ObjectType type = (ObjectType)Convert.ToInt32(item[0]); int version = Convert.ToInt32(item[1]); String ln = GXCommon.ToLogicalName((byte[])item[2]); GXDLMSObject obj = null; if (settings.Objects != null) { obj = settings.Objects.FindByLN(type, ln); } if (obj == null) { obj = Gurux.DLMS.GXDLMSClient.CreateObject(type); obj.LogicalName = ln; obj.Version = version; } //Unknown objects are not shown. if (obj is IGXDLMSBase && item[3] != null) { UpdateAccessRights(obj, (Object[])item[3]); ObjectList.Add(obj); } } } } else if (e.Index == 3) { if (e.Value != null) { ClientSAP = Convert.ToByte(((Object[])e.Value)[0]); ServerSAP = Convert.ToUInt16(((Object[])e.Value)[1]); } } else if (e.Index == 4) { //Value of the object identifier encoded in BER if (e.Value is byte[]) { GXByteBuffer arr = new GXByteBuffer(e.Value as byte[]); if (arr.GetUInt8(0) == 0x60) { ApplicationContextName.JointIsoCtt = 0; ++arr.Position; ApplicationContextName.Country = 0; ++arr.Position; ApplicationContextName.CountryName = 0; ++arr.Position; ApplicationContextName.IdentifiedOrganization = arr.GetUInt8(); ApplicationContextName.DlmsUA = arr.GetUInt8(); ApplicationContextName.ApplicationContext = arr.GetUInt8(); ApplicationContextName.ContextId = arr.GetUInt8(); } else { //Get Tag and Len. if (arr.GetUInt8() != (int)BerType.Integer && arr.GetUInt8() != 7) { throw new ArgumentOutOfRangeException(); } //Get tag if (arr.GetUInt8() != 0x11) { throw new ArgumentOutOfRangeException(); } ApplicationContextName.JointIsoCtt = arr.GetUInt8(); //Get tag if (arr.GetUInt8() != 0x11) { throw new ArgumentOutOfRangeException(); } ApplicationContextName.Country = arr.GetUInt8(); //Get tag if (arr.GetUInt8() != 0x12) { throw new ArgumentOutOfRangeException(); } ApplicationContextName.CountryName = arr.GetUInt16(); //Get tag if (arr.GetUInt8() != 0x11) { throw new ArgumentOutOfRangeException(); } ApplicationContextName.IdentifiedOrganization = arr.GetUInt8(); //Get tag if (arr.GetUInt8() != 0x11) { throw new ArgumentOutOfRangeException(); } ApplicationContextName.DlmsUA = arr.GetUInt8(); //Get tag if (arr.GetUInt8() != 0x11) { throw new ArgumentOutOfRangeException(); } ApplicationContextName.ApplicationContext = arr.GetUInt8(); //Get tag if (arr.GetUInt8() != 0x11) { throw new ArgumentOutOfRangeException(); } ApplicationContextName.ContextId = arr.GetUInt8(); } } else if (e.Value != null) { Object[] arr = (Object[])e.Value; ApplicationContextName.JointIsoCtt = Convert.ToByte(arr[0]); ApplicationContextName.Country = Convert.ToByte(arr[1]); ApplicationContextName.CountryName = Convert.ToUInt16(arr[2]); ApplicationContextName.IdentifiedOrganization = Convert.ToByte(arr[3]); ApplicationContextName.DlmsUA = Convert.ToByte(arr[4]); ApplicationContextName.ApplicationContext = Convert.ToByte(arr[5]); ApplicationContextName.ContextId = Convert.ToByte(arr[6]); } } else if (e.Index == 5) { if (e.Value != null) { Object[] arr = (Object[])e.Value; GXByteBuffer bb = new GXByteBuffer(); GXCommon.SetBitString(bb, arr[0]); bb.SetUInt8(0, 0); XDLMSContextInfo.Conformance = (Conformance)bb.GetUInt32(); XDLMSContextInfo.MaxReceivePduSize = Convert.ToUInt16(arr[1]); XDLMSContextInfo.MaxSendPduSize = Convert.ToUInt16(arr[2]); XDLMSContextInfo.DlmsVersionNumber = Convert.ToByte(arr[3]); XDLMSContextInfo.QualityOfService = Convert.ToSByte(arr[4]); XDLMSContextInfo.CypheringInfo = (byte[])arr[5]; } } else if (e.Index == 6) { //Value of the object identifier encoded in BER if (e.Value is byte[]) { GXByteBuffer arr = new GXByteBuffer(e.Value as byte[]); if (arr.GetUInt8(0) == 0x60) { AuthenticationMechanismName.JointIsoCtt = 0; ++arr.Position; AuthenticationMechanismName.Country = 0; ++arr.Position; AuthenticationMechanismName.CountryName = 0; ++arr.Position; AuthenticationMechanismName.IdentifiedOrganization = arr.GetUInt8(); AuthenticationMechanismName.DlmsUA = arr.GetUInt8(); AuthenticationMechanismName.AuthenticationMechanismName = arr.GetUInt8(); AuthenticationMechanismName.MechanismId = (Authentication)arr.GetUInt8(); } else { //Get Tag and Len. if (arr.GetUInt8() != (int)BerType.Integer && arr.GetUInt8() != 7) { throw new ArgumentOutOfRangeException(); } //Get tag if (arr.GetUInt8() != 0x11) { throw new ArgumentOutOfRangeException(); } AuthenticationMechanismName.JointIsoCtt = arr.GetUInt8(); //Get tag if (arr.GetUInt8() != 0x11) { throw new ArgumentOutOfRangeException(); } AuthenticationMechanismName.Country = arr.GetUInt8(); //Get tag if (arr.GetUInt8() != 0x12) { throw new ArgumentOutOfRangeException(); } AuthenticationMechanismName.CountryName = arr.GetUInt16(); //Get tag if (arr.GetUInt8() != 0x11) { throw new ArgumentOutOfRangeException(); } AuthenticationMechanismName.IdentifiedOrganization = arr.GetUInt8(); //Get tag if (arr.GetUInt8() != 0x11) { throw new ArgumentOutOfRangeException(); } AuthenticationMechanismName.DlmsUA = arr.GetUInt8(); //Get tag if (arr.GetUInt8() != 0x11) { throw new ArgumentOutOfRangeException(); } AuthenticationMechanismName.AuthenticationMechanismName = arr.GetUInt8(); //Get tag if (arr.GetUInt8() != 0x11) { throw new ArgumentOutOfRangeException(); } AuthenticationMechanismName.MechanismId = (Authentication)arr.GetUInt8(); } } else if (e.Value != null) { Object[] arr = (Object[])e.Value; AuthenticationMechanismName.JointIsoCtt = Convert.ToByte(arr[0]); AuthenticationMechanismName.Country = Convert.ToByte(arr[1]); AuthenticationMechanismName.CountryName = Convert.ToUInt16(arr[2]); AuthenticationMechanismName.IdentifiedOrganization = Convert.ToByte(arr[3]); AuthenticationMechanismName.DlmsUA = Convert.ToByte(arr[4]); AuthenticationMechanismName.AuthenticationMechanismName = Convert.ToByte(arr[5]); AuthenticationMechanismName.MechanismId = (Authentication)Convert.ToByte(arr[6]); } } else if (e.Index == 7) { Secret = (byte[])e.Value; } else if (e.Index == 8) { if (e.Value == null) { AssociationStatus = AssociationStatus.NonAssociated; } else { AssociationStatus = (AssociationStatus)Convert.ToInt32(e.Value); } } else if (e.Index == 9) { SecuritySetupReference = GXCommon.ToLogicalName(e.Value); } else { e.Error = ErrorCode.ReadWriteDenied; } }
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 = HlsSecret; } 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.FrameCounter; } else { secret = HlsSecret; } 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; } }
/// <summary> /// Parse User Information from PDU. /// </summary> public static void ParseUserInformation(GXDLMSSettings settings, GXICipher cipher, GXByteBuffer data, GXDLMSTranslatorStructure xml) { byte len = data.GetUInt8(); GXByteBuffer tmp2 = new GXByteBuffer(); tmp2.SetUInt8(0); if (data.Size - data.Position < len) { throw new Exception("Not enough data."); } if (xml != null && xml.OutputType == TranslatorOutputType.StandardXml) { len = (byte)(data.Size - data.Position); xml.AppendLine(Command.InitiateRequest, null, GXCommon .ToHex(data.Data, false, data.Position, len)); data.Position = data.Position + len; return; } //Excoding the choice for user information int tag = data.GetUInt8(); if (tag != 0x4) { throw new Exception("Invalid tag."); } len = data.GetUInt8(); //Tag for xDLMS-Initate.response tag = data.GetUInt8(); if (tag == (byte)Command.GloInitiateResponse) { if (xml != null) { int cnt = GXCommon.GetObjectCount(data); byte[] tmp = new byte[cnt]; data.Get(tmp); //<glo_InitiateResponse> xml.AppendLine(Command.GloInitiateResponse, "Value", GXCommon.ToHex(tmp, false)); return; } --data.Position; cipher.Security = cipher.Decrypt(settings.SourceSystemTitle, data); tag = data.GetUInt8(); } else if (tag == (byte)Command.GloInitiateRequest) { if (xml != null) { int cnt = GXCommon.GetObjectCount(data); byte[] tmp = new byte[cnt]; data.Get(tmp); //<glo_InitiateRequest> xml.AppendLine(Command.GloInitiateRequest, "Value", GXCommon.ToHex(tmp, false)); return; } --data.Position; cipher.Security = cipher.Decrypt(settings.SourceSystemTitle, data); tag = data.GetUInt8(); } bool response = tag == (byte)Command.InitiateResponse; if (response) { if (xml != null) { //<InitiateResponse> xml.AppendStartTag(Command.InitiateResponse); } //Optional usage field of the negotiated quality of service component tag = data.GetUInt8(); len = 0; if (tag != 0)//Skip if used. { len = data.GetUInt8(); data.Position += len; if (len == 0 && xml != null) { //NegotiatedQualityOfService xml.AppendLine(TranslatorGeneralTags.NegotiatedQualityOfService, "Value", "00"); } } } else if (tag == (byte)Command.InitiateRequest) { if (xml != null) { //<InitiateRequest> xml.AppendStartTag(Command.InitiateRequest); } //Optional usage field of the negotiated quality of service component tag = data.GetUInt8(); //CtoS. if (tag != 0) { len = data.GetUInt8(); settings.CtoSChallenge = new byte[len]; data.Get(settings.CtoSChallenge); } //Optional usage field of the negotiated quality of service component tag = data.GetUInt8(); if (tag != 0)//Skip if used. { len = data.GetUInt8(); data.Position += len; } //Optional usage field of the proposed quality of service component tag = data.GetUInt8(); if (tag != 0)//Skip if used. { len = data.GetUInt8(); data.Position += len; } } else { throw new Exception("Invalid tag."); } //Get DLMS version number. if (!response) { if (data.GetUInt8() != 6) { throw new Exception("Invalid DLMS version number."); } //ProposedDlmsVersionNumber if (xml != null) { xml.AppendLine(TranslatorGeneralTags.ProposedDlmsVersionNumber, "Value", xml.IntegerToHex(settings.DLMSVersion, 2)); } } else { if (data.GetUInt8() != 6) { throw new Exception("Invalid DLMS version number."); } if (xml != null) { xml.AppendLine(TranslatorGeneralTags.NegotiatedDlmsVersionNumber, "Value", xml.IntegerToHex(settings.DLMSVersion, 2)); } } //Tag for conformance block tag = data.GetUInt8(); if (tag != 0x5F) { throw new Exception("Invalid tag."); } //Old Way... if (data.GetUInt8(data.Position) == 0x1F) { data.GetUInt8(); } len = data.GetUInt8(); //The number of unused bits in the bit string. tag = data.GetUInt8(); if (!response) { //ProposedConformance if (xml != null) { xml.AppendStartTag(TranslatorGeneralTags.ProposedConformance); } data.Get(settings.ConformanceBlock); tmp2.Set(settings.ConformanceBlock); } else { //NegotiatedConformance if (xml != null) { xml.AppendStartTag(TranslatorGeneralTags.NegotiatedConformance); } if (settings.UseLogicalNameReferencing) { data.Get(settings.LnSettings.ConformanceBlock); tmp2.Set(settings.LnSettings.ConformanceBlock); } else { data.Get(settings.SnSettings.ConformanceBlock); tmp2.Set(settings.SnSettings.ConformanceBlock); } } if (xml != null) { GetConformance(tmp2.GetUInt32(), xml); } if (!response) { //Proposed max PDU size. settings.MaxPduSize = data.GetUInt16(); if (xml != null) { //ProposedConformance closing xml.AppendEndTag(TranslatorGeneralTags.ProposedConformance); //ProposedMaxPduSize xml.AppendLine(TranslatorGeneralTags.ProposedMaxPduSize, "Value", xml.IntegerToHex(settings.MaxPduSize, 4)); } //If client asks too high PDU. if (settings.MaxPduSize > settings.MaxServerPDUSize) { settings.MaxPduSize = settings.MaxServerPDUSize; } } else { //Max PDU size. settings.MaxPduSize = data.GetUInt16(); if (xml != null) { //NegotiatedConformance closing xml.AppendEndTag(TranslatorGeneralTags.NegotiatedConformance); //NegotiatedMaxPduSize xml.AppendLine(TranslatorGeneralTags.NegotiatedMaxPduSize, "Value", xml.IntegerToHex(settings.MaxPduSize, 4)); } } if (response) { //VAA Name tag = data.GetUInt16(); if (xml != null) { xml.AppendLine(TranslatorGeneralTags.VaaName, "Value", xml.IntegerToHex(tag, 4)); } if (tag == 0x0007) { // If LN if (!settings.UseLogicalNameReferencing) { throw new ArgumentException("Invalid VAA."); } } else if (tag == 0xFA00) { // If SN if (settings.UseLogicalNameReferencing) { throw new ArgumentException("Invalid VAA."); } } else { // Unknown VAA. throw new ArgumentException("Invalid VAA."); } if (xml != null) { //<InitiateResponse> xml.AppendEndTag(Command.InitiateResponse); } } else if (xml != null) { //</InitiateRequest> xml.AppendEndTag(Command.InitiateRequest); } }
/// <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); }
/// <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()); }
/// <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(); }
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); }
/// <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); }
///<summary> ///Get UInt32 value from DLMS data. ///</summary> ///<param name="buff"> ///Received DLMS data. ///</param> ///<param name="info"> ///Data info. ///</param> ///<returns> ///Parsed UInt32 value. /// </returns> private static object GetUInt32(GXByteBuffer buff, GXDataInfo info) { // If there is not enough data available. if (buff.Size - buff.Position < 4) { info.Complete = false; return null; } UInt32 value = buff.GetUInt32(); if (info.xml != null) { info.xml.AppendLine(info.xml.GetDataType(info.Type), "Value", value); } return value; }
/// <summary> /// Get object count. If first byte is 0x80 or higger it will tell bytes count. /// </summary> /// <param name="data">Received data.</param> /// <returns>Object count.</returns> public static int GetObjectCount(GXByteBuffer data) { int cnt = data.GetUInt8(); if (cnt > 0x80) { if (cnt == 0x81) { return data.GetUInt8(); } else if (cnt == 0x82) { return data.GetUInt16(); } else if (cnt == 0x84) { return (int)data.GetUInt32(); } else { throw new System.ArgumentException("Invalid count."); } } return cnt; }
/// <summary> /// Get HDLC address from byte array. /// </summary> /// <param name="GXByteBuffer">Byte array.</param> /// <returns>HDLC address.</returns> public static int GetHDLCAddress(GXByteBuffer buff) { int size = 0; for (int pos = buff.Position; pos != buff.Size; ++pos) { ++size; if ((buff.GetUInt8(pos) & 0x1) == 1) { break; } } if (size == 1) { return (byte)((buff.GetUInt8() & 0xFE) >> 1); } else if (size == 2) { size = buff.GetUInt16(); size = ((size & 0xFE) >> 1) | ((size & 0xFE00) >> 2); return size; } else if (size == 4) { UInt32 tmp = buff.GetUInt32(); tmp = ((tmp & 0xFE) >> 1) | ((tmp & 0xFE00) >> 2) | ((tmp & 0xFE0000) >> 3) | ((tmp & 0xFE000000) >> 4); return (int)tmp; } throw new ArgumentException("Wrong size."); }
void IGXDLMSBase.SetValue(GXDLMSSettings settings, ValueEventArgs e) { if (e.Index == 1) { LogicalName = GXCommon.ToLogicalName(e.Value); } else if (e.Index == 2) { ObjectList.Clear(); if (e.Value != null) { foreach (Object[] item in (Object[])e.Value) { GXDLMSObject obj = GetObject(settings, item); //Unknown objects are not shown. if (obj is IGXDLMSBase) { ObjectList.Add(obj); } } } } else if (e.Index == 3) { if (e.Value != null) { ClientSAP = Convert.ToByte(((Object[])e.Value)[0]); ServerSAP = Convert.ToUInt16(((Object[])e.Value)[1]); } } else if (e.Index == 4) { //Value of the object identifier encoded in BER if (e.Value is byte[]) { GXByteBuffer arr = new GXByteBuffer(e.Value as byte[]); if (arr.GetUInt8(0) == 0x60) { ApplicationContextName.JointIsoCtt = arr.GetUInt8(); ApplicationContextName.Country = arr.GetUInt8(); ApplicationContextName.CountryName = arr.GetUInt8(); ApplicationContextName.IdentifiedOrganization = arr.GetUInt8(); ApplicationContextName.DlmsUA = arr.GetUInt8(); ApplicationContextName.ApplicationContext = arr.GetUInt8(); ApplicationContextName.ContextId = (ApplicationContextName)arr.GetUInt8(); } else { //Get Tag and Len. if (arr.GetUInt8() != (int)BerType.Integer && arr.GetUInt8() != 7) { throw new ArgumentOutOfRangeException(); } //Get tag if (arr.GetUInt8() != 0x11) { throw new ArgumentOutOfRangeException(); } ApplicationContextName.JointIsoCtt = arr.GetUInt8(); //Get tag if (arr.GetUInt8() != 0x11) { throw new ArgumentOutOfRangeException(); } ApplicationContextName.Country = arr.GetUInt8(); //Get tag if (arr.GetUInt8() != 0x12) { throw new ArgumentOutOfRangeException(); } ApplicationContextName.CountryName = arr.GetUInt16(); //Get tag if (arr.GetUInt8() != 0x11) { throw new ArgumentOutOfRangeException(); } ApplicationContextName.IdentifiedOrganization = arr.GetUInt8(); //Get tag if (arr.GetUInt8() != 0x11) { throw new ArgumentOutOfRangeException(); } ApplicationContextName.DlmsUA = arr.GetUInt8(); //Get tag if (arr.GetUInt8() != 0x11) { throw new ArgumentOutOfRangeException(); } ApplicationContextName.ApplicationContext = arr.GetUInt8(); //Get tag if (arr.GetUInt8() != 0x11) { throw new ArgumentOutOfRangeException(); } ApplicationContextName.ContextId = (ApplicationContextName)arr.GetUInt8(); } } else if (e.Value != null) { Object[] arr = (Object[])e.Value; ApplicationContextName.JointIsoCtt = Convert.ToByte(arr[0]); ApplicationContextName.Country = Convert.ToByte(arr[1]); ApplicationContextName.CountryName = Convert.ToUInt16(arr[2]); ApplicationContextName.IdentifiedOrganization = Convert.ToByte(arr[3]); ApplicationContextName.DlmsUA = Convert.ToByte(arr[4]); ApplicationContextName.ApplicationContext = Convert.ToByte(arr[5]); ApplicationContextName.ContextId = (ApplicationContextName)Convert.ToByte(arr[6]); } } else if (e.Index == 5) { if (e.Value != null) { Object[] arr = (Object[])e.Value; if (arr[0] is string || arr[0] is byte[]) { GXByteBuffer bb = new GXByteBuffer(); GXCommon.SetBitString(bb, arr[0], true); bb.SetUInt8(0, 0); XDLMSContextInfo.Conformance = (Conformance)bb.GetUInt32(); } else { XDLMSContextInfo.Conformance = (Conformance)Convert.ToUInt16(arr[0]); } XDLMSContextInfo.MaxReceivePduSize = Convert.ToUInt16(arr[1]); XDLMSContextInfo.MaxSendPduSize = Convert.ToUInt16(arr[2]); XDLMSContextInfo.DlmsVersionNumber = Convert.ToByte(arr[3]); XDLMSContextInfo.QualityOfService = Convert.ToSByte(arr[4]); XDLMSContextInfo.CypheringInfo = (byte[])arr[5]; } } else if (e.Index == 6) { //Value of the object identifier encoded in BER if (e.Value is byte[]) { GXByteBuffer arr = new GXByteBuffer(e.Value as byte[]); if (arr.GetUInt8(0) == 0x60) { AuthenticationMechanismName.JointIsoCtt = arr.GetUInt8(); AuthenticationMechanismName.Country = arr.GetUInt8(); AuthenticationMechanismName.CountryName = arr.GetUInt8(); AuthenticationMechanismName.IdentifiedOrganization = arr.GetUInt8(); AuthenticationMechanismName.DlmsUA = arr.GetUInt8(); AuthenticationMechanismName.AuthenticationMechanismName = arr.GetUInt8(); AuthenticationMechanismName.MechanismId = (Authentication)arr.GetUInt8(); } else { //Get Tag and Len. if (arr.GetUInt8() != (int)BerType.Integer && arr.GetUInt8() != 7) { throw new ArgumentOutOfRangeException(); } //Get tag if (arr.GetUInt8() != 0x11) { throw new ArgumentOutOfRangeException(); } AuthenticationMechanismName.JointIsoCtt = arr.GetUInt8(); //Get tag if (arr.GetUInt8() != 0x11) { throw new ArgumentOutOfRangeException(); } AuthenticationMechanismName.Country = arr.GetUInt8(); //Get tag if (arr.GetUInt8() != 0x12) { throw new ArgumentOutOfRangeException(); } AuthenticationMechanismName.CountryName = arr.GetUInt16(); //Get tag if (arr.GetUInt8() != 0x11) { throw new ArgumentOutOfRangeException(); } AuthenticationMechanismName.IdentifiedOrganization = arr.GetUInt8(); //Get tag if (arr.GetUInt8() != 0x11) { throw new ArgumentOutOfRangeException(); } AuthenticationMechanismName.DlmsUA = arr.GetUInt8(); //Get tag if (arr.GetUInt8() != 0x11) { throw new ArgumentOutOfRangeException(); } AuthenticationMechanismName.AuthenticationMechanismName = arr.GetUInt8(); //Get tag if (arr.GetUInt8() != 0x11) { throw new ArgumentOutOfRangeException(); } AuthenticationMechanismName.MechanismId = (Authentication)arr.GetUInt8(); } } else if (e.Value != null) { Object[] arr = (Object[])e.Value; AuthenticationMechanismName.JointIsoCtt = Convert.ToByte(arr[0]); AuthenticationMechanismName.Country = Convert.ToByte(arr[1]); AuthenticationMechanismName.CountryName = Convert.ToUInt16(arr[2]); AuthenticationMechanismName.IdentifiedOrganization = Convert.ToByte(arr[3]); AuthenticationMechanismName.DlmsUA = Convert.ToByte(arr[4]); AuthenticationMechanismName.AuthenticationMechanismName = Convert.ToByte(arr[5]); AuthenticationMechanismName.MechanismId = (Authentication)Convert.ToByte(arr[6]); } } else if (e.Index == 7) { Secret = (byte[])e.Value; } else if (e.Index == 8) { if (e.Value == null) { AssociationStatus = AssociationStatus.NonAssociated; } else { AssociationStatus = (AssociationStatus)Convert.ToInt32(e.Value); } } else if (e.Index == 9) { SecuritySetupReference = GXCommon.ToLogicalName(e.Value); } else if (e.Index == 10) { UserList.Clear(); if (e.Value != null) { foreach (Object[] item in (Object[])e.Value) { UserList.Add(new KeyValuePair <byte, string>(Convert.ToByte(item[0]), Convert.ToString(item[1]))); } } } else if (e.Index == 11) { if (e.Value != null) { Object[] tmp = (Object[])e.Value; if (tmp.Length == 1) { CurrentUser = new KeyValuePair <byte, string>(Convert.ToByte(tmp[0]), null); } else { CurrentUser = new KeyValuePair <byte, string>(Convert.ToByte(tmp[0]), Convert.ToString(tmp[1])); } } else { CurrentUser = new KeyValuePair <byte, string>(0, null); } } else { e.Error = ErrorCode.ReadWriteDenied; } }
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); }