private static void CaptureArray(GXDLMSServer server, GXByteBuffer tmp, GXByteBuffer bb, int index) { //Skip type. tmp.GetUInt8(); int cnt = GXCommon.GetObjectCount(tmp); for (int pos = 0; pos != cnt; ++pos) { if (index == -1 || index == pos) { DataType dt = (DataType)tmp.GetUInt8(tmp.Position); if (dt == DataType.Structure || dt == DataType.Array) { CaptureArray(server, tmp, bb, -1); } else { CaptureValue(server, tmp, bb); } if (index == pos) { break; } } } }
/// <summary> /// Parse application context name. /// </summary> /// <param name="settings">DLMS settings.</param> /// <param name="buff">Received data.</param> private static bool ParseApplicationContextName(GXDLMSSettings settings, GXByteBuffer buff) { //Get length. int len = buff.GetUInt8(); if (buff.Size - buff.Position < len) { throw new Exception("Encoding failed. Not enough data."); } if (buff.GetUInt8() != 0x6) { throw new Exception("Encoding failed. Not an Object ID."); } if (settings.IsServer) { settings.Cipher.Security = Security.None; } //Object ID length. len = buff.GetUInt8(); if (settings.UseLogicalNameReferencing) { if (buff.Compare(GXCommon.LogicalNameObjectID)) { return(true); } // If ciphering is used. return(buff.Compare(GXCommon.LogicalNameObjectIdWithCiphering)); } if (buff.Compare(GXCommon.ShortNameObjectID)) { return(true); } // If ciphering is used. return(buff.Compare(GXCommon.ShortNameObjectIdWithCiphering)); }
/// <summary> /// Get OID string from bytes. /// </summary> /// <param name="bb">converted bytes. </param> /// <param name="len">byte count. </param> /// <returns> OID string. </returns> private static string OidStringFromBytes(GXByteBuffer bb, int len) { long value = 0; StringBuilder sb = new StringBuilder(); if (len != 0) { // Get first byte. int tmp = bb.GetUInt8(); sb.Append(tmp / 40); sb.Append('.'); sb.Append(tmp % 40); for (int pos = 1; pos != len; ++pos) { tmp = bb.GetUInt8(); if ((tmp & 0x80) != 0) { value += (tmp & 0x7F); value <<= 7; } else { value += tmp; sb.Append('.'); sb.Append(value); value = 0; } } } return(sb.ToString()); }
/// <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 void UpdateTemplateDescription(GXByteBuffer columns, GXByteBuffer data, int index) { DataType ch = (DataType)data.GetUInt8(); int count = GXCommon.GetObjectCount(data); if (index == -1) { columns.SetUInt8(ch); if (ch == DataType.Array) { columns.SetUInt16((UInt16)count); } else { columns.SetUInt8((byte)count); } } GXDataInfo info = new GXDataInfo(); for (int pos = 0; pos < count; ++pos) { //If all data is captured. if (index == -1 || pos == index) { DataType dt = (DataType)data.GetUInt8(data.Position); if (dt == DataType.Array || dt == DataType.Structure) { UpdateTemplateDescription(columns, data, -1); if (ch == DataType.Array) { break; } } else { info.Clear(); columns.SetUInt8((byte)dt); //Get data. GXCommon.GetData(null, data, info); } if (index == pos) { break; } } } }
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."); } }
private static void UpdateInterval(GXDLMSInterval interval, byte[] value) { GXByteBuffer bb = new GXByteBuffer(value); byte b = bb.GetUInt8(); interval.StartHour = (byte)(b & 0x1F); interval.IntervalTariff = (DefaultTariffBand)((b >> 5) & 0x3); interval.UseInterval = (b >> 7) != 0; interval.WeeklyActivation = (WeeklyActivation)bb.GetUInt16(); UInt16 v = bb.GetUInt16(); interval.SpecialDayMonth = (byte)(v & 0xF); interval.SpecialDay = (byte)((v >> 8) & 0xF); interval.SpecialDayEnabled = (v >> 15) != 0; }
byte[] IGXDLMSBase.Invoke(GXDLMSSettings settings, ValueEventArgs e) { //Check reply_to_HLS_authentication if (e.Index == 8) { UInt32 ic = 0; byte[] secret; if (settings.Authentication == Authentication.HighGMAC) { secret = settings.SourceSystemTitle; GXByteBuffer bb = new GXByteBuffer(e.Parameters as byte[]); bb.GetUInt8(); ic = bb.GetUInt32(); } else { secret = Secret; } byte[] serverChallenge = GXSecure.Secure(settings, settings.Cipher, ic, settings.StoCChallenge, secret); byte[] clientChallenge = (byte[])e.Parameters; if (GXCommon.Compare(serverChallenge, clientChallenge)) { if (settings.Authentication == Authentication.HighGMAC) { secret = settings.Cipher.SystemTitle; ic = settings.Cipher.InvocationCounter; } else { secret = Secret; } settings.Connected = true; return(GXSecure.Secure(settings, settings.Cipher, ic, settings.CtoSChallenge, secret)); } else { // If the password does not match. settings.Connected = false; return(null); } } else { e.Error = ErrorCode.ReadWriteDenied; return(null); } }
/// <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; */ }
/// <summary> /// Update ephemeral keys. /// </summary> /// <param name="client">DLMS Client.</param> /// <param name="value">Received reply from the server.</param> /// <returns>List of Parsed key id and GUAK. This is for debugging purpose.</returns> public List <KeyValuePair <GlobalKeyType, byte[]> > UpdateEphemeralKeys(GXDLMSSecureClient client, GXByteBuffer value) { if (client == null) { throw new ArgumentNullException(nameof(client)); } if (value.GetUInt8() != (byte)DataType.Array) { throw new ArgumentOutOfRangeException("Invalid tag."); } GXEcdsa c = new GXEcdsa(client.Ciphering.EphemeralKeyPair.Key); int count = GXCommon.GetObjectCount(value); List <KeyValuePair <GlobalKeyType, byte[]> > list = new List <KeyValuePair <GlobalKeyType, byte[]> >(); for (int pos = 0; pos != count; ++pos) { if (value.GetUInt8() != (byte)DataType.Structure) { throw new ArgumentOutOfRangeException("Invalid tag."); } if (value.GetUInt8() != 2) { throw new ArgumentOutOfRangeException("Invalid length."); } if (value.GetUInt8() != (byte)DataType.Enum) { throw new ArgumentOutOfRangeException("Invalid key id data type."); } int keyId = value.GetUInt8(); if (keyId > 4) { throw new ArgumentOutOfRangeException("Invalid key type."); } if (value.GetUInt8() != (byte)DataType.OctetString) { throw new ArgumentOutOfRangeException("Invalid tag."); } if (GXCommon.GetObjectCount(value) != 128) { throw new ArgumentOutOfRangeException("Invalid length."); } //Get ephemeral public key server. GXByteBuffer key = new GXByteBuffer(); key.SetUInt8(4); key.Set(value, 64); GXPublicKey targetEphemeralKey = GXPublicKey.FromRawBytes(key.Array()); //Get ephemeral public key signature server. byte[] signature = new byte[64]; value.Get(signature); key.SetUInt8(0, (byte)keyId); //Verify signature. if (!GXSecure.ValidateEphemeralPublicKeySignature(key.Array(), signature, client.Ciphering.SigningKeyPair.Value)) { throw new GXDLMSCipherException("Invalid signature."); } byte[] z = c.GenerateSecret(targetEphemeralKey); System.Diagnostics.Debug.WriteLine("Shared secret:" + GXCommon.ToHex(z, true)); GXByteBuffer kdf = new GXByteBuffer(); kdf.Set(GXSecure.GenerateKDF(client.SecuritySuite, z, AlgorithmId.AesGcm128, client.Ciphering.SystemTitle, client.Settings.SourceSystemTitle, null, null)); System.Diagnostics.Debug.WriteLine("KDF:" + kdf.ToString()); list.Add(new KeyValuePair <GlobalKeyType, byte[]>((GlobalKeyType)keyId, kdf.SubArray(0, 16))); } //Update ephemeral keys. foreach (KeyValuePair <GlobalKeyType, byte[]> it in list) { switch (it.Key) { case GlobalKeyType.UnicastEncryption: client.Settings.EphemeralBlockCipherKey = it.Value; break; case GlobalKeyType.BroadcastEncryption: client.Settings.EphemeralBroadcastBlockCipherKey = it.Value; break; case GlobalKeyType.Authentication: client.Settings.EphemeralAuthenticationKey = it.Value; break; case GlobalKeyType.Kek: client.Settings.EphemeralKek = it.Value; break; } } return(list); }
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; } }
/// <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); } }
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> /// 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(); }
///<summary> ///Parse APDU. ///</summary> static internal SourceDiagnostic ParsePDU(GXDLMSSettings settings, GXICipher cipher, GXByteBuffer buff, GXDLMSTranslatorStructure xml) { // Get AARE tag and length int tag = buff.GetUInt8(); if (settings.IsServer) { if (tag != ((byte)BerType.Application | (byte)BerType.Constructed | (byte)PduType.ProtocolVersion)) { throw new Exception("Invalid tag."); } } else { if (tag != ((byte)BerType.Application | (byte)BerType.Constructed | (byte)PduType.ApplicationContextName)) { throw new Exception("Invalid tag."); } } int len = buff.GetUInt8(); int size = buff.Size - buff.Position; if (len > size) { throw new Exception("Not enough data."); } //Opening tags if (xml != null) { if (settings.IsServer) { xml.AppendStartTag(Command.Aarq); } else { xml.AppendStartTag(Command.Aare); } } AssociationResult resultComponent = AssociationResult.Accepted; SourceDiagnostic resultDiagnosticValue = SourceDiagnostic.None; while (buff.Position < buff.Size) { tag = buff.GetUInt8(); switch (tag) { case (byte)BerType.Context | (byte)BerType.Constructed | (byte)PduType.ApplicationContextName://0xA1 if (!ParseApplicationContextName(settings, buff, xml)) { throw new GXDLMSException(AssociationResult.PermanentRejected, SourceDiagnostic.ApplicationContextNameNotSupported); } break; case (byte)BerType.Context | (byte)BerType.Constructed | (byte)PduType.CalledApTitle://0xA2 //Get len. if (buff.GetUInt8() != 3) { throw new Exception("Invalid tag."); } //Choice for result (INTEGER, universal) if (buff.GetUInt8() != (byte)BerType.Integer) { throw new Exception("Invalid tag."); } //Get len. if (buff.GetUInt8() != 1) { throw new Exception("Invalid tag."); } resultComponent = (AssociationResult)buff.GetUInt8(); if (xml != null) { xml.AppendLine(TranslatorGeneralTags.AssociationResult, "Value", xml.IntegerToHex((int)resultComponent, 2)); xml.AppendStartTag(TranslatorGeneralTags.ResultSourceDiagnostic); } break; case (byte)BerType.Context | (byte)BerType.Constructed | (byte)PduType.CalledAeQualifier:////SourceDiagnostic 0xA3 len = buff.GetUInt8(); // ACSE service user tag. tag = buff.GetUInt8(); len = buff.GetUInt8(); // Result source diagnostic component. if (buff.GetUInt8() != (byte)BerType.Integer) { throw new Exception("Invalid tag."); } if (buff.GetUInt8() != 1) { throw new Exception("Invalid tag."); } resultDiagnosticValue = (SourceDiagnostic)buff.GetUInt8(); if (xml != null) { xml.AppendLine(TranslatorGeneralTags.ACSEServiceUser, "Value", xml.IntegerToHex((int)resultDiagnosticValue, 2)); xml.AppendEndTag(TranslatorGeneralTags.ResultSourceDiagnostic); } break; case (byte)BerType.Context | (byte)BerType.Constructed | (byte)PduType.CalledApInvocationId: ////Result 0xA4 //Get len. if (buff.GetUInt8() != 0xA) { throw new Exception("Invalid tag."); } //Choice for result (Universal, Octetstring type) if (buff.GetUInt8() != (byte)BerType.OctetString) { throw new Exception("Invalid tag."); } //responding-AP-title-field //Get len. len = buff.GetUInt8(); settings.SourceSystemTitle = new byte[len]; buff.Get(settings.SourceSystemTitle); if (xml != null) { //RespondingAPTitle xml.AppendLine(TranslatorGeneralTags.RespondingAPTitle, "Value", GXCommon.ToHex(settings.SourceSystemTitle, false)); } break; //Client Challenge. case (byte)BerType.Context | (byte)BerType.Constructed | (byte)PduType.CallingApTitle://0xA6 len = buff.GetUInt8(); tag = buff.GetUInt8(); len = buff.GetUInt8(); settings.SourceSystemTitle = new byte[len]; buff.Get(settings.SourceSystemTitle); if (xml != null) { //CallingAPTitle xml.AppendLine(TranslatorGeneralTags.CallingAPTitle, "Value", GXCommon.ToHex(settings.SourceSystemTitle, false)); } break; //Server Challenge. case (byte)BerType.Context | (byte)BerType.Constructed | (byte)PduType.SenderAcseRequirements://0xAA len = buff.GetUInt8(); tag = buff.GetUInt8(); len = buff.GetUInt8(); settings.StoCChallenge = new byte[len]; buff.Get(settings.StoCChallenge); AppendServerSystemTitleToXml(settings, xml, tag); break; case (byte)BerType.Context | (byte)PduType.SenderAcseRequirements: //0x8A case (byte)BerType.Context | (byte)PduType.CallingApInvocationId: //0x88 //Get sender ACSE-requirements field component. if (buff.GetUInt8() != 2) { throw new Exception("Invalid tag."); } if (buff.GetUInt8() != (byte)BerType.ObjectDescriptor) { throw new Exception("Invalid tag."); } if (buff.GetUInt8() != 0x80) { throw new Exception("Invalid tag."); } //SenderACSERequirements if (xml != null) { xml.AppendLine(tag, "Value", "1"); } break; case (byte)BerType.Context | (byte)PduType.MechanismName://0x8B case (byte)BerType.Context | (byte)PduType.CallingAeInvocationId://0x89 UpdateAuthentication(settings, buff); if (xml != null) { if (xml.OutputType == TranslatorOutputType.SimpleXml) { xml.AppendLine(tag, "Value", settings.Authentication.ToString()); } else { xml.AppendLine(tag, "Value", ((int)settings.Authentication).ToString()); } } break; case (byte)BerType.Context | (byte)BerType.Constructed | (byte)PduType.CallingAuthenticationValue://0xAC updatePassword(settings, buff, xml); break; case (byte)BerType.Context | (byte)BerType.Constructed | (byte)PduType.UserInformation: //0xBE if (xml == null && resultComponent != AssociationResult.Accepted && resultDiagnosticValue != SourceDiagnostic.None) { throw new GXDLMSException(resultComponent, resultDiagnosticValue); } ParseUserInformation(settings, cipher, buff, xml); break; default: //Unknown tags. System.Diagnostics.Debug.WriteLine("Unknown tag: " + tag + "."); if (buff.Position < buff.Size) { len = buff.GetUInt8(); buff.Position += (UInt16)len; } break; } } //Closing tags if (xml != null) { if (settings.IsServer) { xml.AppendEndTag(Command.Aarq); } else { xml.AppendEndTag(Command.Aare); } } return resultDiagnosticValue; }
/// <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."); }
///<summary> ///Convert Bit string to DLMS bytes. ///</summary> ///<param name="buff"> ///Byte buffer where data is write. ///</param> ///<param name="value"> ///Added value. ///</param> private static void SetBitString(GXByteBuffer buff, object value) { if (value is string) { GXByteBuffer tmp = new GXByteBuffer(); byte val = 0; int index = 0; string str = ((string)value); SetObjectCount(str.Length, buff); foreach (char it in str.Reverse()) { if (it == '1') { val |= (byte)(1 << index); ++index; } else if (it == '0') { ++index; } else { throw new Exception("Not a bit string."); } if (index == 8) { index = 0; tmp.SetUInt8(val); val = 0; } } if (index != 0) { tmp.SetUInt8(val); } for (int pos = tmp.Size - 1; pos != -1; --pos) { buff.SetUInt8(tmp.GetUInt8(pos)); } } else if (value is sbyte[]) { byte[] arr = (byte[])value; SetObjectCount(arr.Length, buff); buff.Set(arr); } else if (value == null) { buff.SetUInt8(0); } else { throw new Exception("BitString must give as string."); } }
///<summary> ///Get boolean value from DLMS data. ///</summary> ///<param name="buff"> ///Received DLMS data. ///</param> ///<param name="info"> ///Data info. ///</param> ///<returns> ///Parsed boolean value. ///</returns> private static object GetBoolean(GXByteBuffer buff, GXDataInfo info) { // If there is not enough data available. if (buff.Size - buff.Position < 1) { info.Complete = false; return null; } byte value = buff.GetUInt8(); if (info.xml != null) { info.xml.AppendLine(GXDLMS.DATA_TYPE_OFFSET + (int)info.Type, "Value", value); } return value != 0; }
///<summary> ///Get bit string value from DLMS data. ///</summary> ///<param name="buff"> ///Received DLMS data. ///</param> ///<param name="info"> ///Data info. ///</param> ///<returns> ///Parsed bit string value. ///</returns> private static string GetBitString(GXByteBuffer buff, GXDataInfo info) { int cnt = GetObjectCount(buff); double t = cnt; t /= 8; if (cnt % 8 != 0) { ++t; } int byteCnt = (int)Math.Floor(t); // If there is not enough data available. if (buff.Size - buff.Position < byteCnt) { info.Complete = false; return null; } StringBuilder sb = new StringBuilder(); while (cnt > 0) { ToBitString(sb, buff.GetUInt8(), cnt); cnt -= 8; } if (info.xml != null) { info.xml.AppendLine(info.xml.GetDataType(info.Type), "Value", sb.ToString()); } return sb.ToString(); }
/// <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"); } 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()); }
void IGXDLMSBase.SetValue(GXDLMSSettings settings, ValueEventArgs e) { if (e.Index == 1) { if (e.Value is string) { LogicalName = e.Value.ToString(); } else { LogicalName = GXDLMSClient.ChangeType((byte[])e.Value, DataType.OctetString).ToString(); } } 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 = GXDLMSObject.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; XDLMSContextInfo.Conformance = arr[0].ToString(); XDLMSContextInfo.MaxReceivePduSize = Convert.ToUInt16(arr[1]); XDLMSContextInfo.MaxSendPpuSize = 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) { AuthenticationMechanismMame.JointIsoCtt = 0; ++arr.Position; AuthenticationMechanismMame.Country = 0; ++arr.Position; AuthenticationMechanismMame.CountryName = 0; ++arr.Position; AuthenticationMechanismMame.IdentifiedOrganization = arr.GetUInt8(); AuthenticationMechanismMame.DlmsUA = arr.GetUInt8(); AuthenticationMechanismMame.AuthenticationMechanismName = arr.GetUInt8(); AuthenticationMechanismMame.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(); } AuthenticationMechanismMame.JointIsoCtt = arr.GetUInt8(); //Get tag if (arr.GetUInt8() != 0x11) { throw new ArgumentOutOfRangeException(); } AuthenticationMechanismMame.Country = arr.GetUInt8(); //Get tag if (arr.GetUInt8() != 0x12) { throw new ArgumentOutOfRangeException(); } AuthenticationMechanismMame.CountryName = arr.GetUInt16(); //Get tag if (arr.GetUInt8() != 0x11) { throw new ArgumentOutOfRangeException(); } AuthenticationMechanismMame.IdentifiedOrganization = arr.GetUInt8(); //Get tag if (arr.GetUInt8() != 0x11) { throw new ArgumentOutOfRangeException(); } AuthenticationMechanismMame.DlmsUA = arr.GetUInt8(); //Get tag if (arr.GetUInt8() != 0x11) { throw new ArgumentOutOfRangeException(); } AuthenticationMechanismMame.AuthenticationMechanismName = arr.GetUInt8(); //Get tag if (arr.GetUInt8() != 0x11) { throw new ArgumentOutOfRangeException(); } AuthenticationMechanismMame.MechanismId = (Authentication)arr.GetUInt8(); } } else if (e.Value != null) { Object[] arr = (Object[])e.Value; AuthenticationMechanismMame.JointIsoCtt = Convert.ToByte(arr[0]); AuthenticationMechanismMame.Country = Convert.ToByte(arr[1]); AuthenticationMechanismMame.CountryName = Convert.ToUInt16(arr[2]); AuthenticationMechanismMame.IdentifiedOrganization = Convert.ToByte(arr[3]); AuthenticationMechanismMame.DlmsUA = Convert.ToByte(arr[4]); AuthenticationMechanismMame.AuthenticationMechanismName = Convert.ToByte(arr[5]); AuthenticationMechanismMame.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 = GXDLMSClient.ChangeType((byte[])e.Value, DataType.OctetString).ToString(); } else { e.Error = ErrorCode.ReadWriteDenied; } }
///<summary> ///Get data from DLMS frame. ///</summary> ///<param name="settings">DLMS settings.</param> ///<param name="data">Received data.</param> ///<param name="info"> Data info.</param> ///<returns>Parsed object.</returns> /// public static object GetData(GXDLMSSettings settings, GXByteBuffer data, GXDataInfo info) { object value = null; int startIndex = data.Position; if (data.Position == data.Size) { info.Complete = false; return null; } info.Complete = true; bool knownType = info.Type != DataType.None; // Get data type if it is unknown. if (!knownType) { info.Type = (DataType)data.GetUInt8(); } if (info.Type == DataType.None) { if (info.xml != null) { info.xml.AppendLine("<" + info.xml.GetDataType(info.Type) + " />"); } return value; } if (data.Position == data.Size) { info.Complete = false; return null; } switch (info.Type) { case DataType.Array: case DataType.Structure: value = GetArray(data, info, startIndex); break; case DataType.Boolean: value = GetBoolean(data, info); break; case DataType.BitString: value = GetBitString(data, info); break; case DataType.Int32: value = GetInt32(data, info); break; case DataType.UInt32: value = GetUInt32(data, info); break; case DataType.String: value = GetString(data, info, knownType); break; case DataType.StringUTF8: value = GetUtfString(data, info, knownType); break; case DataType.OctetString: value = GetOctetString(data, info, knownType); break; case DataType.Bcd: value = GetBcd(data, info, knownType); break; case DataType.Int8: value = GetInt8(data, info); break; case DataType.Int16: value = GetInt16(data, info); break; case DataType.UInt8: value = GetUInt8(data, info); break; case DataType.UInt16: value = GetUInt16(data, info); break; case DataType.CompactArray: throw new Exception("Invalid data type."); case DataType.Int64: value = GetInt64(data, info); break; case DataType.UInt64: value = GetUInt64(data, info); break; case DataType.Enum: value = GetEnum(data, info); break; case DataType.Float32: value = Getfloat(data, info); break; case DataType.Float64: value = GetDouble(data, info); break; case DataType.DateTime: value = GetDateTime(settings, data, info); break; case DataType.Date: value = GetDate(data, info); break; case DataType.Time: value = GetTime(data, info); break; default: throw new Exception("Invalid data type."); } return value; }
private static void UpdateAuthentication(GXDLMSSettings settings, GXByteBuffer buff) { byte len = buff.GetUInt8(); if (buff.GetUInt8() != 0x60) { throw new Exception("Invalid tag."); } if (buff.GetUInt8() != 0x85) { throw new Exception("Invalid tag."); } if (buff.GetUInt8() != 0x74) { throw new Exception("Invalid tag."); } if (buff.GetUInt8() != 0x05) { throw new Exception("Invalid tag."); } if (buff.GetUInt8() != 0x08) { throw new Exception("Invalid tag."); } if (buff.GetUInt8() != 0x02) { throw new Exception("Invalid tag."); } int tmp = buff.GetUInt8(); if (tmp < 0 || tmp > 7) { throw new Exception("Invalid tag."); } settings.Authentication = (Authentication)tmp; }
///<summary> ///Get time from DLMS data. ///</summary> ///<param name="buff"> ///Received DLMS data. ///</param> ///<param name="info"> ///Data info. ///</param> ///<returns> ///Parsed time. ///</returns> private static object GetTime(GXByteBuffer buff, GXDataInfo info) { object value; if (buff.Size - buff.Position < 4) { // If there is not enough data available. info.Complete = false; return null; } if (info.xml != null) { info.xml.AppendLine(info.xml.GetDataType(info.Type), "Value", GXCommon.ToHex(buff.Data, false, buff.Position, 4)); } // Get time. int hour = buff.GetUInt8(); int minute = buff.GetUInt8(); int second = buff.GetUInt8(); int ms = buff.GetUInt8(); if (ms != 0xFF) { ms *= 10; } GXTime dt = new GXTime(hour, minute, second, ms); value = dt; return value; }
///<summary> ///Get date from DLMS data. ///</summary> ///<param name="buff"> ///Received DLMS data. ///</param> ///<param name="info"> ///Data info. ///</param> ///<returns> ///Parsed date. ///</returns> private static object GetDate(GXByteBuffer buff, GXDataInfo info) { object value; if (buff.Size - buff.Position < 5) { // If there is not enough data available. info.Complete = false; return null; } if (info.xml != null) { info.xml.AppendLine(info.xml.GetDataType(info.Type), "Value", GXCommon.ToHex(buff.Data, false, buff.Position, 5)); } // Get year. int year = buff.GetUInt16(); // Get month int month = buff.GetUInt8(); // Get day int day = buff.GetUInt8(); GXDate dt = new GXDate(year, month, day); // Skip week day if (buff.GetUInt8() == 0xFF) { dt.Skip |= DateTimeSkips.DayOfWeek; } value = dt; return value; }
///<summary> ///Get date and time from DLMS data. ///</summary> ///<param name="settings">DLMS settings.</param> ///<param name="buff">Received DLMS data.</param> ///<param name="info">Data info.</param> ///<returns> ///Parsed date and time. ///</returns> private static object GetDateTime(GXDLMSSettings settings, GXByteBuffer buff, GXDataInfo info) { // If there is not enough data available. if (buff.Size - buff.Position < 12) { //If time. if (buff.Size - buff.Position < 5) { return GetTime(buff, info); } //If date. else if (buff.Size - buff.Position < 6) { return GetDate(buff, info); } info.Complete = false; return null; } if (info.xml != null) { info.xml.AppendLine(info.xml.GetDataType(info.Type), "Value", GXCommon.ToHex(buff.Data, false, buff.Position, 12)); } GXDateTime dt = new GXDateTime(); //Get year. int year = buff.GetUInt16(); if (year == 0xFFFF || year == 0) { year = DateTime.Now.Year; dt.Skip |= DateTimeSkips.Year; } //Get month int month = buff.GetUInt8(); if (month == 0 || month == 0xFF || month == 0xFE || month == 0xFD) { month = 1; dt.Skip |= DateTimeSkips.Month; } int day = buff.GetUInt8(); if (day < 1 || day == 0xFF) { day = 1; dt.Skip |= DateTimeSkips.Day; } else if (day == 0xFD || day == 0xFE) { day = DateTime.DaysInMonth(year, month) + (sbyte)day + 2; } //Skip week day if (buff.GetUInt8() == 0xFF) { dt.Skip |= DateTimeSkips.DayOfWeek; } //Get time. int hours = buff.GetUInt8(); if (hours == 0xFF) { hours = 0; dt.Skip |= DateTimeSkips.Hour; } int minutes = buff.GetUInt8(); if (minutes == 0xFF) { minutes = 0; dt.Skip |= DateTimeSkips.Minute; } int seconds = buff.GetUInt8(); if (seconds == 0xFF) { seconds = 0; dt.Skip |= DateTimeSkips.Second; } int milliseconds = buff.GetUInt8(); if (milliseconds != 0xFF) { milliseconds *= 10; } else { milliseconds = 0; dt.Skip |= DateTimeSkips.Ms; } int deviation = buff.GetInt16(); dt.Status = (ClockStatus)buff.GetUInt8(); if (settings != null && settings.UtcTimeZone) { deviation = -deviation; } dt.Deviation = deviation; //0x8000 == -32768 //deviation = -1 if skipped. if (deviation != -1 && deviation != -32768 && year != 1 && (dt.Skip & DateTimeSkips.Year) == 0) { dt.Value = new DateTimeOffset(new DateTime(year, month, day, hours, minutes, seconds, milliseconds), new TimeSpan(0, -deviation, 0)); } else //Use current time if deviation is not defined. { dt.Skip |= DateTimeSkips.Devitation; DateTime tmp = new DateTime(year, month, day, hours, minutes, seconds, milliseconds, DateTimeKind.Local); dt.Value = new DateTimeOffset(tmp, TimeZoneInfo.Local.GetUtcOffset(tmp)); } return dt; }
/// <summary> /// Parse application context name. /// </summary> /// <param name="settings">DLMS settings.</param> /// <param name="buff">Received data.</param> private static bool ParseApplicationContextName(GXDLMSSettings settings, GXByteBuffer buff, GXDLMSTranslatorStructure xml) { //Get length. int len = buff.GetUInt8(); if (buff.Size - buff.Position < len) { throw new Exception("Encoding failed. Not enough data."); } if (buff.GetUInt8() != 0x6) { throw new Exception("Encoding failed. Not an Object ID."); } if (settings.IsServer && settings.Cipher != null) { settings.Cipher.Security = Gurux.DLMS.Enums.Security.None; } //Object ID length. len = buff.GetUInt8(); if (xml != null) { if (buff.Compare(GXCommon.LogicalNameObjectID)) { if (xml.OutputType == TranslatorOutputType.SimpleXml) { xml.AppendLine(TranslatorGeneralTags.ApplicationContextName, "Value", "LN"); } else { xml.AppendLine( TranslatorGeneralTags.ApplicationContextName, null, "1"); } settings.UseLogicalNameReferencing = true; } else if (buff.Compare(GXCommon.LogicalNameObjectIdWithCiphering)) { if (xml.OutputType == TranslatorOutputType.SimpleXml) { xml.AppendLine(TranslatorGeneralTags.ApplicationContextName, "Value", "LN_WITH_CIPHERING"); } else { xml.AppendLine( TranslatorGeneralTags.ApplicationContextName, null, "3"); } settings.UseLogicalNameReferencing = true; } else if (buff.Compare(GXCommon.ShortNameObjectID)) { if (xml.OutputType == TranslatorOutputType.SimpleXml) { xml.AppendLine(TranslatorGeneralTags.ApplicationContextName, "Value", "SN"); } else { xml.AppendLine( TranslatorGeneralTags.ApplicationContextName, null, "2"); } settings.UseLogicalNameReferencing = false; } else if (buff.Compare(GXCommon.ShortNameObjectIdWithCiphering)) { if (xml.OutputType == TranslatorOutputType.SimpleXml) { xml.AppendLine(TranslatorGeneralTags.ApplicationContextName, "Value", "SN_WITH_CIPHERING"); } else { xml.AppendLine( TranslatorGeneralTags.ApplicationContextName, null, "4"); } settings.UseLogicalNameReferencing = false; } else { return false; } return true; } if (settings.UseLogicalNameReferencing) { if (buff.Compare(GXCommon.LogicalNameObjectID)) { return true; } // If ciphering is used. return buff.Compare(GXCommon.LogicalNameObjectIdWithCiphering); } if (buff.Compare(GXCommon.ShortNameObjectID)) { return true; } // If ciphering is used. return buff.Compare(GXCommon.ShortNameObjectIdWithCiphering); }
///<summary> ///Get enumeration value from DLMS data. ///</summary> ///<param name="buff"> ///Received DLMS data. ///</param> ///<param name="info"> ///Data info. ///</param> ///<returns> ///Parsed enumeration value. ///</returns> private static object GetEnum(GXByteBuffer buff, GXDataInfo info) { // If there is not enough data available. if (buff.Size - buff.Position < 1) { info.Complete = false; return null; } byte value = buff.GetUInt8(); if (info.xml != null) { info.xml.AppendLine(info.xml.GetDataType(info.Type), "Value", info.xml.IntegerToHex(value, 2)); } return value; }
private static void GetValue(GXByteBuffer bb, IList <object> objects, GXAsn1Settings s) { int len; short type; IList <object> tmp; byte[] tmp2; type = bb.GetUInt8(); len = GXCommon.GetObjectCount(bb); if (len > bb.Available) { throw new OutOfMemoryException("GXAsn1Converter.GetValue"); } int connectPos = 0; if (s != null) { connectPos = s.XmlLength; } int start = bb.Position; string tagString = null; if (s != null) { s.AppendSpaces(); if (type == (byte)BerType.Integer) { if (len == 1 || len == 2 || len == 4 || len == 8) { tagString = s.GetTag((short)-len); } else { tagString = s.GetTag((byte)BerType.Integer); } } else { tagString = s.GetTag(type); } s.Append("<" + tagString + ">"); } switch (type) { case (byte)(BerType.Constructed | BerType.Context): case ((byte)(BerType.Constructed | BerType.Context) | 1): case ((byte)(BerType.Constructed | BerType.Context) | 2): case ((byte)(BerType.Constructed | BerType.Context) | 3): case ((byte)(BerType.Constructed | BerType.Context) | 4): if (s != null) { s.Increase(); } tmp = new GXAsn1Context() { Index = type & 0xF }; objects.Add(tmp); while (bb.Position < start + len) { GetValue(bb, tmp, s); } if (s != null) { s.Decrease(); } break; case (byte)(BerType.Constructed | BerType.Sequence): if (s != null) { s.Increase(); } tmp = new GXAsn1Sequence(); objects.Add(tmp); int cnt = 0; while (bb.Position < start + len) { ++cnt; GetValue(bb, tmp, s); } if (s != null) { // Append comment. s.AppendComment(connectPos, Convert.ToString(cnt) + " elements."); s.Decrease(); } break; case (byte)(BerType.Constructed | BerType.Set): if (s != null) { s.Increase(); } tmp = new List <object>(); GetValue(bb, tmp, s); if (tmp[0] is GXAsn1Sequence) { tmp = (GXAsn1Sequence)tmp[0]; objects.Add(new KeyValuePair <object, object>(tmp[0], tmp[1])); } else { KeyValuePair <object, object> e = new KeyValuePair <object, object>(tmp, null); objects.Add(e); } if (s != null) { s.Decrease(); } break; case (byte)BerType.ObjectIdentifier: GXAsn1ObjectIdentifier oi = new GXAsn1ObjectIdentifier(bb, len); objects.Add(oi); if (s != null) { string str = oi.Description; if (str != null) { s.AppendComment(connectPos, str); } s.Append(oi.ToString()); } break; case (byte)BerType.PrintableString: objects.Add(bb.GetString(len)); if (s != null) { s.Append(Convert.ToString(objects[objects.Count - 1])); } break; case (byte)BerType.Utf8StringTag: objects.Add(new GXAsn1Utf8String(bb.GetString(bb.Position, len))); bb.Position = bb.Position + len; if (s != null) { s.Append(Convert.ToString(objects[objects.Count - 1])); } break; case (byte)BerType.Ia5String: objects.Add(new GXAsn1Ia5String(bb.GetString(len))); if (s != null) { s.Append(Convert.ToString(objects[objects.Count - 1])); } break; case (byte)BerType.Integer: if (len == 1) { objects.Add(bb.GetInt8()); } else if (len == 2) { objects.Add(bb.GetInt16()); } else if (len == 4) { objects.Add(bb.GetInt32()); } else { tmp2 = new byte[len]; bb.Get(tmp2); objects.Add(new GXAsn1Integer(tmp2)); } if (s != null) { s.Append(Convert.ToString(objects[objects.Count - 1])); } break; case (byte)BerType.Null: objects.Add(null); break; case (byte)BerType.BitString: GXAsn1BitString tmp3 = new GXAsn1BitString(bb.SubArray(bb.Position, len)); objects.Add(tmp3); bb.Position = bb.Position + len; if (s != null) { // Append comment. s.AppendComment(connectPos, Convert.ToString(tmp3.Length) + " bit."); s.Append(tmp3.asString()); } break; case (byte)BerType.UtcTime: tmp2 = new byte[len]; bb.Get(tmp2); objects.Add(GetUtcTime(ASCIIEncoding.ASCII.GetString(tmp2))); if (s != null) { s.Append(((DateTimeOffset)objects[objects.Count - 1]).UtcDateTime.ToString("yyyy-MM-dd HH:mm", CultureInfo.InvariantCulture)); } break; case (byte)BerType.GeneralizedTime: tmp2 = new byte[len]; bb.Get(tmp2); objects.Add(GXCommon.GetGeneralizedTime(ASCIIEncoding.ASCII.GetString(tmp2))); if (s != null) { s.Append(Convert.ToString(objects[objects.Count - 1])); } break; case (byte)BerType.Context: case (byte)BerType.Context | 1: case (byte)BerType.Context | 2: case (byte)BerType.Context | 3: tmp = new GXAsn1Context() { Constructed = false, Index = type & 0xF }; tmp2 = new byte[len]; bb.Get(tmp2); tmp.Add(tmp2); objects.Add(tmp); if (s != null) { s.Append(GXCommon.ToHex(tmp2, false)); } break; case (byte)BerType.OctetString: int t = bb.GetUInt8(bb.Position); switch (t) { case (byte)(BerType.Constructed | BerType.Sequence): case (byte)BerType.BitString: if (s != null) { s.Increase(); } GetValue(bb, objects, s); if (s != null) { s.Decrease(); } break; default: tmp2 = new byte[len]; bb.Get(tmp2); objects.Add(tmp2); if (s != null) { s.Append(GXCommon.ToHex(tmp2, false)); } break; } break; case (byte)BerType.Boolean: bool b = bb.GetUInt8() != 0; objects.Add(b); if (s != null) { s.Append(Convert.ToString(b)); } break; default: throw new System.ArgumentException("Invalid type: " + type); } if (s != null) { s.Append("</" + tagString + ">\r\n"); } }
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; } }
/// <summary> /// Parse User Information from PDU. /// </summary> private static void ParseUserInformation(GXDLMSSettings settings, GXICipher cipher, GXByteBuffer data) { byte len = data.GetUInt8(); if (data.Size - data.Position < len) { throw new Exception("Not enough data."); } //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 == GXCommon.InitialResponceGlo) { --data.Position; cipher.Security = cipher.Decrypt(settings.SourceSystemTitle, data); tag = data.GetUInt8(); } else if (tag == GXCommon.InitialRequestGlo) { --data.Position; cipher.Security = cipher.Decrypt(settings.SourceSystemTitle, data); tag = data.GetUInt8(); } bool response = tag == GXCommon.InitialResponce; if (response) { //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; } } else if (tag == GXCommon.InitialRequest) { //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 (settings.IsServer) { settings.DlmsVersionNumber = data.GetUInt8(); } else { if (data.GetUInt8() != 6) { throw new Exception("Invalid DLMS version number."); } } //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 (settings.UseLogicalNameReferencing) { if (settings.IsServer) { //Skip settings what client asks. //All server settings are always returned. byte[] tmp = new byte[3]; data.Get(tmp); } else { data.Get(settings.LnSettings.ConformanceBlock); } } else { if (settings.IsServer) { //Skip settings what client asks. //All server settings are always returned. byte[] tmp = new byte[3]; data.Get(tmp); } else { data.Get(settings.SnSettings.ConformanceBlock); } } if (settings.IsServer) { data.GetUInt16(); } else { settings.MaxReceivePDUSize = data.GetUInt16(); } if (response) { //VAA Name tag = data.GetUInt16(); 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."); } } }
/// <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> ///Parse APDU. ///</summary> static internal SourceDiagnostic ParsePDU(GXDLMSSettings settings, GXICipher cipher, GXByteBuffer buff) { // Get AARE tag and length int tag = buff.GetUInt8(); if (settings.IsServer) { if (tag != ((byte)BerType.Application | (byte)BerType.Constructed | (byte)PduType.ProtocolVersion)) { throw new Exception("Invalid tag."); } } else { if (tag != ((byte)BerType.Application | (byte)BerType.Constructed | (byte)PduType.ApplicationContextName)) { throw new Exception("Invalid tag."); } } int len = buff.GetUInt8(); int size = buff.Size - buff.Position; if (len > size) { throw new Exception("Not enough data."); } AssociationResult resultComponent = AssociationResult.Accepted; SourceDiagnostic resultDiagnosticValue = SourceDiagnostic.None; while (buff.Position < buff.Size) { tag = buff.GetUInt8(); switch (tag) { case (byte)BerType.Context | (byte)BerType.Constructed | (byte)PduType.ApplicationContextName: //0xA1 if (!ParseApplicationContextName(settings, buff)) { throw new GXDLMSException(AssociationResult.PermanentRejected, SourceDiagnostic.ApplicationContextNameNotSupported); } break; case (byte)BerType.Context | (byte)BerType.Constructed | (byte)PduType.CalledApTitle: ////Result 0xA2 //Get len. if (buff.GetUInt8() != 3) { throw new Exception("Invalid tag."); } //Choice for result (INTEGER, universal) if (buff.GetUInt8() != (byte)BerType.Integer) { throw new Exception("Invalid tag."); } //Get len. if (buff.GetUInt8() != 1) { throw new Exception("Invalid tag."); } resultComponent = (AssociationResult)buff.GetUInt8(); break; case (byte)BerType.Context | (byte)BerType.Constructed | (byte)PduType.CalledAeQualifier: ////SourceDiagnostic 0xA3 len = buff.GetUInt8(); // ACSE service user tag. tag = buff.GetUInt8(); len = buff.GetUInt8(); // Result source diagnostic component. if (buff.GetUInt8() != (byte)BerType.Integer) { throw new Exception("Invalid tag."); } if (buff.GetUInt8() != 1) { throw new Exception("Invalid tag."); } resultDiagnosticValue = (SourceDiagnostic)buff.GetUInt8(); break; case (byte)BerType.Context | (byte)BerType.Constructed | (byte)PduType.CalledApInvocationId: ////Result 0xA4 //Get len. if (buff.GetUInt8() != 0xA) { throw new Exception("Invalid tag."); } //Choice for result (Universal, Octetstring type) if (buff.GetUInt8() != (byte)BerType.OctetString) { throw new Exception("Invalid tag."); } //responding-AP-title-field //Get len. len = buff.GetUInt8(); settings.SourceSystemTitle = new byte[len]; buff.Get(settings.SourceSystemTitle); break; //Client Challenge. case (byte)BerType.Context | (byte)BerType.Constructed | (byte)PduType.CallingApTitle: //0xA6 len = buff.GetUInt8(); tag = buff.GetUInt8(); len = buff.GetUInt8(); settings.SourceSystemTitle = new byte[len]; buff.Get(settings.SourceSystemTitle); break; //Server Challenge. case (byte)BerType.Context | (byte)BerType.Constructed | (byte)PduType.SenderAcseRequirements: //0xAA len = buff.GetUInt8(); tag = buff.GetUInt8(); len = buff.GetUInt8(); settings.StoCChallenge = new byte[len]; buff.Get(settings.StoCChallenge); break; case (byte)BerType.Context | (byte)PduType.SenderAcseRequirements: //0x8A case (byte)BerType.Context | (byte)PduType.CallingApInvocationId: //0x88 //Get sender ACSE-requirements field component. if (buff.GetUInt8() != 2) { throw new Exception("Invalid tag."); } if (buff.GetUInt8() != (byte)BerType.ObjectDescriptor) { throw new Exception("Invalid tag."); } if (buff.GetUInt8() != 0x80) { throw new Exception("Invalid tag."); } break; case (byte)BerType.Context | (byte)PduType.MechanismName: //0x8B case (byte)BerType.Context | (byte)PduType.CallingAeInvocationId: //0x89 len = buff.GetUInt8(); if (buff.GetUInt8() != 0x60) { throw new Exception("Invalid tag."); } if (buff.GetUInt8() != 0x85) { throw new Exception("Invalid tag."); } if (buff.GetUInt8() != 0x74) { throw new Exception("Invalid tag."); } if (buff.GetUInt8() != 0x05) { throw new Exception("Invalid tag."); } if (buff.GetUInt8() != 0x08) { throw new Exception("Invalid tag."); } if (buff.GetUInt8() != 0x02) { throw new Exception("Invalid tag."); } int tmp = buff.GetUInt8(); if (tmp < 0 || tmp > 5) { throw new Exception("Invalid tag."); } settings.Authentication = (Authentication)tmp; break; case (byte)BerType.Context | (byte)BerType.Constructed | (byte)PduType.CallingAuthenticationValue: //0xAC len = buff.GetUInt8(); // Get authentication information. if (buff.GetUInt8() != 0x80) { throw new Exception("Invalid tag."); } len = buff.GetUInt8(); if (settings.Authentication < Authentication.HighMD5) { settings.Password = new byte[len]; buff.Get(settings.Password); } else { settings.CtoSChallenge = new byte[len]; buff.Get(settings.CtoSChallenge); } break; case (byte)BerType.Context | (byte)BerType.Constructed | (byte)PduType.UserInformation: //0xBE if (resultComponent != AssociationResult.Accepted && resultDiagnosticValue != SourceDiagnostic.None) { throw new GXDLMSException(resultComponent, resultDiagnosticValue); } ParseUserInformation(settings, cipher, buff); break; default: //Unknown tags. System.Diagnostics.Debug.WriteLine("Unknown tag: " + tag + "."); len = buff.GetUInt8(); buff.Position += (UInt16)len; break; } } return(resultDiagnosticValue); }
void IGXDLMSBase.SetValue(GXDLMSSettings settings, ValueEventArgs e) { switch (e.Index) { case 1: LogicalName = GXCommon.ToLogicalName(e.Value); break; case 2: AccountStatus = (AccountStatus)((object[])e.Value)[0]; PaymentMode = (PaymentMode)((object[])e.Value)[1]; break; case 3: CurrentCreditInUse = (byte)e.Value; break; case 4: if ((string)e.Value == "") { CurrentCreditStatus = (AccountCreditStatus)0; } else { GXByteBuffer bb = new GXByteBuffer(); GXCommon.SetBitString(bb, e.Value); CurrentCreditStatus = (AccountCreditStatus)bb.GetUInt8(1); } break; case 5: AvailableCredit = (int)e.Value; break; case 6: AmountToClear = (int)e.Value; break; case 7: ClearanceThreshold = (int)e.Value; break; case 8: AggregatedDebt = (int)e.Value; break; case 9: CreditReferences.Clear(); if (e.Value != null) { foreach (object it in (object[])e.Value) { CreditReferences.Add(GXCommon.ToLogicalName(it)); } } break; case 10: ChargeReferences.Clear(); if (e.Value != null) { foreach (object it in (object[])e.Value) { ChargeReferences.Add(GXCommon.ToLogicalName(it)); } } break; case 11: CreditChargeConfigurations.Clear(); if (e.Value != null) { foreach (object[] it in (object[])e.Value) { GXCreditChargeConfiguration item = new GXCreditChargeConfiguration(); item.CreditReference = GXCommon.ToLogicalName(it[0]); item.ChargeReference = GXCommon.ToLogicalName(it[1]); if ((string)it[2] == "") { item.CollectionConfiguration = 0; } else { GXByteBuffer tmp2 = new GXByteBuffer(); GXCommon.SetBitString(tmp2, it[2]); item.CollectionConfiguration = (CreditCollectionConfiguration)tmp2.GetUInt8(1); } CreditChargeConfigurations.Add(item); } } break; case 12: TokenGatewayConfigurations.Clear(); if (e.Value != null) { foreach (object[] it in (object[])e.Value) { GXTokenGatewayConfiguration item = new GXTokenGatewayConfiguration(); item.CreditReference = GXCommon.ToLogicalName(it[0]); item.TokenProportion = (byte)it[1]; TokenGatewayConfigurations.Add(item); } } break; case 13: if (e.Value == null) { AccountActivationTime = new GXDateTime(DateTime.MinValue); } else { if (e.Value is byte[]) { e.Value = GXDLMSClient.ChangeType((byte[])e.Value, DataType.DateTime, settings.UseUtc2NormalTime); } else if (e.Value is string) { e.Value = new GXDateTime((string)e.Value); } if (e.Value is GXDateTime) { AccountActivationTime = (GXDateTime)e.Value; } } break; case 14: if (e.Value == null) { AccountClosureTime = new GXDateTime(DateTime.MinValue); } else { if (e.Value is byte[]) { e.Value = GXDLMSClient.ChangeType((byte[])e.Value, DataType.DateTime, settings.UseUtc2NormalTime); } else if (e.Value is string) { e.Value = new GXDateTime((string)e.Value); } if (e.Value is GXDateTime) { AccountClosureTime = (GXDateTime)e.Value; } } break; case 15: object[] tmp = (object[])e.Value; Currency.Name = (string)tmp[0]; Currency.Scale = (sbyte)tmp[1]; Currency.Unit = (Currency)tmp[2]; break; case 16: LowCreditThreshold = (int)e.Value; break; case 17: NextCreditAvailableThreshold = (int)e.Value; break; case 18: MaxProvision = (UInt16)e.Value; break; case 19: MaxProvisionPeriod = (int)e.Value; break; default: e.Error = ErrorCode.ReadWriteDenied; break; } }
/// <summary> /// Client has send data for for the gateway. /// </summary> /// <remarks> /// GW finds the correct client and sends data for it. /// </remarks> /// <param name="sender"></param> /// <param name="e"></param> public static void OnGatewayReceived(object sender, Gurux.Common.ReceiveEventArgs e) { try { lock (buffers) { GXByteBuffer bb; if (!buffers.ContainsKey(e.SenderInfo)) { bb = new GXByteBuffer(); buffers[e.SenderInfo] = bb; } else { bb = buffers[e.SenderInfo]; } bb.Set((byte[])e.Data); GXServerReply sr = new GXServerReply(bb.Data); GatewayServer.Reset(); try { GatewayServer.HandleRequest(sr); if (sr.Reply != null) { if (Trace > TraceLevel.Info) { Console.WriteLine("TX:\t" + Gurux.Common.GXCommon.ToHex(sr.Reply, true)); } ((IGXMedia)sender).Send(sr.Reply, e.SenderInfo); return; } } catch (Exception) { //Return error. sr.Reply = GatewayServer.ReportError(sr.Command, ErrorCode.HardwareFault); } if (sr.Gateway != null && sr.Data != null) { GXByteBuffer pdu = new GXByteBuffer(sr.Data); InterfaceType type = (InterfaceType)sr.Gateway.NetworkId; GXByteBuffer address = new GXByteBuffer(); address.Set(sr.Gateway.PhysicalDeviceAddress); int addr = address.GetUInt8(); //Find correct meter using GW information. if (meters.ContainsKey(addr)) { //Find client for the server or create a new one. GXDLMSClient cl; if (!clients.ContainsKey(addr)) { //Set client address if data is send without framing. if (GatewayServer.Settings.ClientAddress == 0) { GatewayServer.Settings.ClientAddress = 0x10; } cl = new GXDLMSClient(true, GatewayServer.Settings.ClientAddress, addr, GatewayServer.Authentication, null, type); clients.Add(addr, cl); } else { cl = clients[addr]; } GXReplyData data = new GXReplyData(); GXReplyData notify = new GXReplyData(); GXDLMSMeter m = meters[addr]; //Send SNRM if needed. if (sr.Command == Command.Aarq && (type == InterfaceType.HDLC || type == InterfaceType.HdlcWithModeE)) { GXServerReply sr2 = new GXServerReply(cl.SNRMRequest()); m.HandleRequest(sr2); if (cl.GetData(sr2.Reply, data, notify)) { data.Clear(); notify.Clear(); } else { //If the meter doesn't reply. bb.Clear(); return; } } byte[][] frames = cl.CustomFrameRequest(Command.None, pdu); foreach (byte[] it in frames) { sr.Data = it; m.HandleRequest(sr); if (Trace > TraceLevel.Info) { Console.WriteLine("RX:\t" + Gurux.Common.GXCommon.ToHex(sr.Reply, true)); } data.RawPdu = true; if (cl.GetData(sr.Reply, data, notify)) { while (data.IsMoreData) { sr.Data = cl.ReceiverReady(data); m.HandleRequest(sr); if (Trace > TraceLevel.Info) { Console.WriteLine("RX:\t" + Gurux.Common.GXCommon.ToHex(sr.Reply, true)); } cl.GetData(sr.Reply, data, notify); } byte[] reply = sr.Reply; try { GXByteBuffer tmp = new GXByteBuffer(); tmp.Set(data.Data); GatewayServer.Gateway = sr.Gateway; reply = GatewayServer.CustomFrameRequest(Command.None, tmp); } finally { GatewayServer.Gateway = null; } if (Trace > TraceLevel.Info) { Console.WriteLine("TX:\t" + Gurux.Common.GXCommon.ToHex(reply, true)); } ((IGXMedia)sender).Send(reply, e.SenderInfo); } } } bb.Clear(); } } } catch (Exception ex) { if (!(ex is SocketException)) { Console.WriteLine(ex.Message); } } }
/// <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); }
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); }
private static void updatePassword(GXDLMSSettings settings, GXByteBuffer buff, GXDLMSTranslatorStructure xml) { int len = buff.GetUInt8(); // Get authentication information. if (buff.GetUInt8() != 0x80) { throw new Exception("Invalid tag."); } len = buff.GetUInt8(); if (settings.Authentication == Authentication.Low) { settings.Password = new byte[len]; buff.Get(settings.Password); } else { settings.CtoSChallenge = new byte[len]; buff.Get(settings.CtoSChallenge); } if (xml != null) { if (xml.OutputType == TranslatorOutputType.SimpleXml) { if (settings.Authentication == Authentication.Low) { xml.AppendLine(TranslatorGeneralTags.CallingAuthentication, "Value", GXCommon.ToHex(settings.Password, false)); } else { xml.AppendLine(TranslatorGeneralTags.CallingAuthentication, "Value", GXCommon.ToHex(settings.CtoSChallenge, false)); } } else { xml.AppendStartTag( TranslatorGeneralTags.CallingAuthentication); xml.AppendStartTag(TranslatorGeneralTags.CharString); if (settings.Authentication == Authentication.Low) { xml.Append(GXCommon.ToHex(settings.Password, false)); } else { xml.Append( GXCommon.ToHex(settings.CtoSChallenge, false)); } xml.AppendEndTag(TranslatorGeneralTags.CharString); xml.AppendEndTag(TranslatorGeneralTags.CallingAuthentication); } } }
void IGXDLMSBase.SetValue(GXDLMSSettings settings, ValueEventArgs e) { switch (e.Index) { case 1: LogicalName = GXCommon.ToLogicalName(e.Value); break; case 2: CurrentCreditAmount = (int)e.Value; break; case 3: Type = (CreditType)(byte)e.Value; break; case 4: Priority = (byte)e.Value; break; case 5: WarningThreshold = (int)e.Value; break; case 6: Limit = (int)e.Value; break; case 7: if ((string)e.Value == "") { CreditConfiguration = (CreditConfiguration)0; } else { GXByteBuffer bb = new GXByteBuffer(); GXCommon.SetBitString(bb, e.Value, true); CreditConfiguration = (CreditConfiguration)bb.GetUInt8(1); } break; case 8: Status = (CreditStatus)(byte)e.Value; break; case 9: PresetCreditAmount = (int)e.Value; break; case 10: CreditAvailableThreshold = (int)e.Value; break; case 11: if (e.Value == null) { Period = new GXDateTime(DateTime.MinValue); } else { if (e.Value is byte[]) { e.Value = GXDLMSClient.ChangeType((byte[])e.Value, DataType.DateTime, settings.UseUtc2NormalTime); } else if (e.Value is string) { e.Value = new GXDateTime((string)e.Value); } if (e.Value is GXDateTime) { Period = (GXDateTime)e.Value; } } break; default: e.Error = ErrorCode.ReadWriteDenied; break; } }
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); }