Invocation counter
Invocation counter a.k.a Frame counter is a counter value that is increased every time when a message is ciphered. Increasing invocation counter causes that messages are encrypted differently, even the content is the same.The invocation counter is not used non-ciphered messages. Invocation counter value is usually saved to the data-object. If invocation counter is not correct, the meter will not accept the message. There might be several invocation counters on the meter. There is usually one invocation counter for each secured association. With some meters, there might be own invocation counter for optical port connection and own invocation counter for TCP/IP connection.
Client side
Before starting the ciphered connection client must establish a normal connection (usually this is done without authentication) and read the invocation counter from the meter. After reading the counter value connection is closed. There is a -I parameter in client examples that is reading invocation counter from the meter. You can use parameter like this:-I 0.0.43.1.0.255
GXDLMSData client = new GXDLMSClient(); // Is used Logican Name or Short Name referencing. client.setUseLogicalNameReferencing(true); client.setInterfaceType(InterfaceType.HDLC); client.setClientAddress(16); client.setServerAddress(1); //Send SNRM request and parse UA response //Send AARQ request and parse AARE response //Read invocation counter. GXDLMSData d = new GXDLMSData("OBIS_CODE"); read(d, 2); client.getCiphering().setInvocationCounter(1 + ((Number)d.Value)); //Close the connection. disconnect();
GXDLMSClient client = new GXDLMSClient(); // Is used Logican Name or Short Name referencing. client.UseLogicalNameReferencing = true; // Is used HDLC or COSEM transport layers for IPv4 networks (IEC 62056-47) client.InterfaceType = InterfaceType.Hdlc; client.ClientAddress = 16; client.ServerAddress = 1; //Send SNRM request and parse UA response //Send AARQ request and parse AARE response //Read invocation counter. GXDLMSData d = new GXDLMSData("OBIS_CODE"); Read(d, 2); Client.Ciphering.InvocationCounter = 1 + Convert.ToUInt32(d.Value); //Close the connection. Disconnect();
Client := TGXDLMSClient.Create( // Is used Logican Name or Short Name referencing. True, //Client ID 16, //Server ID 1, //Authentication Level. TAuthentication.None, //PassWord Nil, // Is used HDLC or COSEM transport layers for IPv4 networks (IEC 62056-47) TInterfaceType.General); //Send SNRM request and parse UA response //Send AARQ request and parse AARE response //Read invocation counter. d := TGXDLMSData.Create("OBIS_CODE"); Read(d, 2); Client.Ciphering.InvocationCounter := 1 + d.Value.AsInteger; FreeAndNil(d); //Close the connection. Disconnect();
CGXDLMSClient cl( // Is used Logican Name or Short Name referencing. true, //Client ID 16, //Server ID 1, //Authentication Level. GXDLMS_AUTHENTICATION_LOW, //PassWord "ABCDEFGH", // Is used HDLC or COSEM transport layers for IPv4 networks (IEC 62056-47) GXDLMS_INTERFACETYPE_HDLC); //Send SNRM request and parse UA response //Send AARQ request and parse AARE response //Read invocation counter. CGXDLMSData d("OBIS_CODE"); Read(d, 2); client.GetCiphering()->SetInvocationCounter(1 + d.GetValue().ToInteger()); //Close the connection. Disconnect();
connection con; //Support trace. con_init(&con, 1); //Initialize settings using Logican Name referencing and WRAPPER. cl_init(&con.settings, // Is used Logican Name or Short Name referencing. 1, //Client ID 16, //Server ID 1, //Authentication Level. DLMS_AUTHENTICATION_NONE, //Password NULL, // Is used HDLC or COSEM transport layers for IPv4 networks (IEC 62056-47) DLMS_INTERFACE_TYPE_HDLC); /Send SNRM request and parse UA response //Send AARQ request and parse AARE response //Read invocation counter. gxData d; const unsigned char ln[6] = { 0,0,43, 1, 0, 255}; cosem_init(BASE(d), DLMS_OBJECT_TYPE_DATA, ln); if ((ret = com_read(&con, BASE(d), 2)) == 0) { con.settings.cipher.invocationCounter = 1 + var_toInteger(&d.value); } //Close the connection. com_disconnect(&con);
client = GXDLMSClient() #Is used Logican Name or Short Name referencing. client.useLogicalNameReferencing = True #Is used HDLC or COSEM transport layers for IPv4 networks (IEC 62056-47) client.interfaceType = InterfaceType.HDLC client.clientAddress = 16 client.serverAddress = 1 //Send SNRM request and parse UA response //Send AARQ request and parse AARE response //Read invocation counter. d = GXDLMSData("OBIS_CODE") read(d, 2) client.ciphering.invocationCounter = 1 + d.value
Server side
There is no link from the Security Setup object to the invocation counter data object. This causes that this must add manually to the server side code. This is done adding association view and invocation counter object as normal.//Add logical name association object. GXDLMSAssociationLogicalName ln = new GXDLMSAssociationLogicalName(); ln.setSecuritySetupReference("0.0.43.0.0.255"); getItems().add(ln); //Add security setup object. GXDLMSSecuritySetup ss = new GXDLMSSecuritySetup("0.0.43.0.0.255"); ss.setServerSystemTitle(getCiphering().getSystemTitle()); getItems().add(ss); //Add invocation counter GXDLMSData d = new GXDLMSData("0.0.43.1.0.255"); d.setDataType(2, DataType.UInt32); //Set initial value for invocation counter. d.setValue(100); getItems().add(d);
//Add logical name association object. GXDLMSAssociationLogicalName ln = new GXDLMSAssociationLogicalName(); ln.SecuritySetupReference = "0.0.43.0.0.255"; Items.Add(ln); //Add security setup object. GXDLMSSecuritySetup ss = new GXDLMSSecuritySetup("0.0.43.0.0.255"); ss.ServerSystemTitle = this.Ciphering.SystemTitle; Items.Add(ss); //Add invocation counter GXDLMSData d = new GXDLMSData("0.0.43.1.0.255"); d.SetDataType(2, DataType.UInt32); //Set initial value for invocation counter. d.Value = (UInt32)100; Items.Add(d);
//Add logical name association object. CGXDLMSAssociationLogicalName* ln = new CGXDLMSAssociationLogicalName(); ln->SetSecuritySetupReference("0.0.43.0.0.255"); GetItems().push_back(ln); //Add security setup object. CGXDLMSSecuritySetup* ss = new CGXDLMSSecuritySetup("0.0.43.0.0.255"); ss->SetServerSystemTitle(GetCiphering()->GtSystemTitle()); GetItems().push_back(ss); //Add invocation counter CGXDLMSData* d = new CGXDLMSData("0.0.43.1.0.255"); d->SetDataType(2, DLMS_DATA_TYPE_UINT32); //Set initial value for invocation counter. CGXDLMSVariant v = (unsigned short)100; d->SetValue(v); GetItems().push_back(d);
int ret; //User list. static gxUser USER_LIST[10] = { 0 }; //Dedicated key. static unsigned char CYPHERING_INFO[20] = { 0 }; const unsigned char ln[6] = { 0, 0, 40, 0, 3, 255 }; if ((ret = INIT_OBJECT(highAssociation, DLMS_OBJECT_TYPE_ASSOCIATION_LOGICAL_NAME, ln)) == 0) { highAssociation.authenticationMechanismName.mechanismId = DLMS_AUTHENTICATION_HIGH; OA_ATTACH(highAssociation.objectList, ALL_OBJECTS); #ifndef DLMS_IGNORE_OBJECT_POINTERS highAssociation.securitySetup = &securitySetup; #else memcpy(highAssociation.securitySetupReference, securitySetup.base.logicalName, 6); #endif //DLMS_IGNORE_OBJECT_POINTERS BB_ATTACH(highAssociation.xDLMSContextInfo.cypheringInfo, CYPHERING_INFO, 0); //All objects are add for this Association View later. ARR_ATTACH(highAssociation.userList, USER_LIST, 0); highAssociation.clientSAP = 0x30; static char HLS_PASSWORD[20] = "Gurux"; BB_ATTACH(highAssociation.secret, (unsigned char*)HLS_PASSWORD, (unsigned short)strlen(HLS_PASSWORD)); const unsigned char ln[6] = { 0,0,43, 1, 0, 255}; cosem_init2(&frameCounterHigh.base, DLMS_OBJECT_TYPE_DATA, ln); var_setUInt32(&frameCounterHigh.value, 100); }
@Override public final boolean isTarget(final int serverAddress, final int clientAddress) { //Update invocation counter. if (clientAddress == 1) { getCiphering().setInvocationCounter(((Number) frameCounterHigh.getValue()).intValue()); } return true; }
protected override bool IsTarget(int serverAddress, int clientAddress) { //Update invocation counter. if (clientAddress == 1) { Ciphering.InvocationCounter = Convert.ToUInt32(frameCounterHigh.Value); } return true; }
bool CGXDLMSBase::IsTarget( unsigned long int serverAddress, unsigned long clientAddress) { //Update invocation counter. if (clientAddress == 1) { GetCipher()->SetInvocationCounter(frameCounterHigh.GetValue().ToInteger()); } return true; }
unsigned char svr_isTarget( dlmsSettings* settings, unsigned long serverAddress, unsigned long clientAddress) { //Update invocation counter. if (clientAddress == 1) { settings->cipher.invocationCounter = frameCounterHigh.value.lVal; } }