Skip to main content
Home
for DLMS smart meters

Main navigation

  • Home
  • Products
  • About us
  • Open Source
  • Community
  • Forum
  • Downloads
User account menu
  • Log in

Breadcrumb

  1. Home
  2. Creating Server With HighGMAC Authentication and Association

Creating server with HighGMAC authentication and association

Profile picture for user jack 001
By jack 001, 2 July, 2025
Forums
Gurux DLMS for ANSI C++

Hi
Using Gurux DLMS CPP i managed to create cpp server. as of now i'm able to setup its parameter for connection and add registers as well as the profile generics. currently the server is using Low authentication, now i would like the server to have HighGMac authentication. in Gurux C it looks quite simple, just need to declare the security object, add its association, and add its security setup.
How can i do this in cpp? any hint in the code for me to look up to? thanks in advance

Regards
jack

Profile picture for user Kurumi

Kurumi

3 months 3 weeks ago

Hi, This is done in the same…

Hi,

This is done in the same way. You need to add security object and association object. Then update the correct authentication and block cipher keys in isTarget.

You can check this if you use the default block cipher and authentication keys and just add new association view object and set the authentication level to GMAC.

You can get the default keys from here:
https://github.com/Gurux/Gurux.DLMS.cpp/blob/1d48796032ed936a61debc615a…

BR,
Mikko

Profile picture for user jack 001

jack 001

3 months 3 weeks ago

Hi, thanks for the response…

Hi, thanks for the response.

As per your suggestion, I tried to do it like this

// 1. GXDLMSServerLN.h
class CGXDLMSServerLN :
   public CGXDLMSBase
{
public:
   //Constructor.
   CGXDLMSServerLN(CGXDLMSAssociationLogicalName* ln,
       CGXDLMSIecHdlcSetup* hdlc) : CGXDLMSBase(ln, hdlc)
   {
       // CGXDLMSSecuritySetup* pSecurity = new CGXDLMSSecuritySetup("0.0.43.0.2.255");
       // CGXByteBuffer systemTitle;
       // set Authentication key and Block cipher key
       CGXByteBuffer AuthKey;
       CGXByteBuffer BlockKey;
       AuthKey.AddString("000102030405060708090A0B0C0D0E0F");
       BlockKey.AddString("D0D1D2D3D4D5D6D7D8D9DADBDCDDDEDF");
       // set frame counter
       uint32_t invocationCounter = 0;
       // add cipher
       CGXCipher* cipher = new CGXCipher("4150490000000001");
       cipher->SetAuthenticationKey(AuthKey);
       cipher->SetBlockCipherKey(BlockKey);
       cipher->SetSecurity(DLMS_SECURITY_AUTHENTICATION_ENCRYPTION);
       cipher->SetSecuritySuite(DLMS_SECURITY_SUITE_V0);
       cipher->SetInvocationCounter(invocationCounter);
   
       ln->SetClientSAP(10);
       ln->SetServerSAP(11);
       CGXByteBuffer password;
       password.AddString("API0001");
       ln->SetSecret(password);
   }
};

2. GXDLMSBase.cpp

/*
* Add invocation counter
*/
void AddInvocationCounter(CGXDLMSObjectCollection& items, CGXCipher* cipher)
{
   // Create a new Data object for the invocation counter with the standard logical name.
   CGXDLMSData* pData = new CGXDLMSData("0.0.43.1.0.255");
   // Set the initial value (as unsigned 32-bit integer).
   uint32_t initialValue = cipher->GetInvocationCounter();
   
   CGXDLMSVariant invocationCounter0(initialValue);
   pData->SetValue(invocationCounter0);
   
   // Add the object to the collection.
   items.push_back(pData);
}

// void AddInvocationCounter(CGXDLMSObjectCollection& items, CGXDLMSSecuritySetup* pSecurity)
// {
//     // CGXCipher* cipher = items..GetCipher();
//     CGXDLMSData* pData = new CGXDLMSData("0.0.43.1.0.255");
//     CGXDLMSVariant invocationCounter0;
//     invocationCounter0 = pSecurity->GetInvocationCounter();
//     pData->SetValue(invocationCounter0);
//     items.push_back(pData);
// }

/*
* Add security setup object
*/
CGXDLMSSecuritySetup* AddSecuritySetupHighGmac(CGXDLMSObjectCollection& items)
{
   CGXDLMSSecuritySetup* pSecurity = new CGXDLMSSecuritySetup("0.0.43.0.2.255");
   std::string secLn;
   pSecurity->GetLogicalName(secLn);
   std::cout << "SecuritySetup LN: " << secLn << std::endl;
   
   CGXByteBuffer serverSystemTitle, clientSystemTitle;
   serverSystemTitle.AddString("API 1");
   clientSystemTitle.AddString(nullptr); // Set client system title to null or empty if not used.
   // serverSystemTitle.AddIntAsString(12345);
   std::cout<<"server system title: "<< serverSystemTitle.ToString().c_str()<<std::endl;
   std::cout<<"server system title size: "<<serverSystemTitle.GetSize()<<std::endl;
   std::cout<<"server system title hex: "<<serverSystemTitle.ToHexString(false).c_str()<<std::endl;
   pSecurity->SetServerSystemTitle(serverSystemTitle);
   pSecurity->SetClientSystemTitle(clientSystemTitle);
   std::cout << "ServerSystemTitle size: " << pSecurity->GetServerSystemTitle().GetSize() << std::endl;
   std::cout << "ClientSystemTitle size: " << pSecurity->GetClientSystemTitle().GetSize() << std::endl;
   pSecurity->SetSecurityPolicy(DLMS_SECURITY_POLICY_AUTHENTICATED_ENCRYPTED);
   pSecurity->SetSecuritySuite(DLMS_SECURITY_SUITE_V0);
   pSecurity->SetVersion(0);
   items.push_back(pSecurity);
   return pSecurity;
}
/*
* Add highGMAC association
*/
CGXDLMSAssociationLogicalName* AddAssociationHighGmac(CGXDLMSObjectCollection& items, CGXDLMSSecuritySetup* pSecurity)
{
   CGXDLMSAssociationLogicalName* a = new CGXDLMSAssociationLogicalName("0.0.40.0.4.255");
   std::string ln;
   pSecurity->GetLogicalName(ln);
   a->GetAuthenticationMechanismName().SetMechanismId(
       DLMS_AUTHENTICATION_HIGH_GMAC);
   a->SetClientSAP(1);
   // a->SetServerSAP(1); // example, match your server address
   a->SetSecuritySetupReference(ln);
   a->GetXDLMSContextInfo().SetMaxReceivePduSize(512);
   a->GetXDLMSContextInfo().SetMaxSendPduSize(512);
   a->GetXDLMSContextInfo().SetConformance(
       (DLMS_CONFORMANCE)(
           DLMS_CONFORMANCE_BLOCK_TRANSFER_WITH_ACTION |
           DLMS_CONFORMANCE_GENERAL_PROTECTION |
           DLMS_CONFORMANCE_BLOCK_TRANSFER_WITH_SET_OR_WRITE |
           DLMS_CONFORMANCE_BLOCK_TRANSFER_WITH_GET_OR_READ |
           DLMS_CONFORMANCE_SET |
           DLMS_CONFORMANCE_SELECTIVE_ACCESS |
           DLMS_CONFORMANCE_ACTION |
           DLMS_CONFORMANCE_MULTIPLE_REFERENCES |
           DLMS_CONFORMANCE_GET));
   items.push_back(a);
   return a;
}
// Init
///////////////////////////////////////////////////////////////////////
//Add highgmac security and association objects.
CGXDLMSSecuritySetup* secHighGmac = AddSecuritySetupHighGmac(GetItems());
CGXDLMSAssociationLogicalName* assocHighGmac = AddAssociationHighGmac(GetItems(), secHighGmac);
uint64_t invocationCounterInit;
CGXDLMSSettings& settings = GetSettings();
AddInvocationCounter(GetItems(), GetCiphering()); // Set initial value as needed
std::string secRef = assocHighGmac->GetSecuritySetupReference();
std::cout << "Association SecuritySetupReference: " << secRef << std::endl;
// istarget stuff
bool CGXDLMSBase::IsTarget(
   unsigned long int serverAddress,
   unsigned long clientAddress)
{
   std::cout<< "IsTarget called with serverAddress: " << serverAddress
            << " and clientAddress: " << clientAddress << std::endl;
   // CGXDLMSSettings& settings = GetSettings();
   std::string name = "0.0.40.0.5.255";
   uint16_t pos;
   std::string lnTemp;
   unsigned char ret = 0;
   // std::vector<CGXDLMSObject*> associations;
   CGXDLMSAssociationLogicalName* ln = (CGXDLMSAssociationLogicalName*)GetItems().FindByLN(
                                       DLMS_OBJECT_TYPE_ASSOCIATION_LOGICAL_NAME, name);
   ln->GetLogicalName(lnTemp);
   std::cout << "Association Logical Name: " << lnTemp << std::endl;
   const unsigned short expectedServerAddress = ln->GetServerSAP();
   const unsigned short expectedClientAddress = ln->GetClientSAP();
   if (serverAddress == expectedServerAddress &&
       clientAddress == expectedClientAddress)
   {
       return true;
   }
   for (auto obj : GetItems())
   {
       if (obj->GetObjectType() == DLMS_OBJECT_TYPE_ASSOCIATION_LOGICAL_NAME)
       {
           auto assoc = static_cast<CGXDLMSAssociationLogicalName*>(obj);
           if (assoc->GetClientSAP() == clientAddress)
           {
               // Optionally check serverAddress, security setup, etc.
               // Set settings as needed
               std::string ln;
               // assoc->GetLogicalName(ln);
               CGXCipher* cipher = GetSettings().GetCipher();
               ln = "0.0.43.1.0.255";
               CGXDLMSData* invocationCounter = (CGXDLMSData*)GetItems().FindByLN(DLMS_OBJECT_TYPE_DATA, ln);
               if (invocationCounter) {
                   int value = invocationCounter->GetValue().ToInteger();
                   value++;
                   CGXDLMSVariant v;
                   v = value;
                   invocationCounter->SetValue(v);
                   std::cout << "Updated Invocation Counter Value: " << value << std::endl;
                   std::cout << "Invocation Counter Value: " << invocationCounter->GetValue().ToString().c_str() << std::endl;
                   if (cipher) {
                       cipher->SetInvocationCounter(value++);
                   }
               }
               return true;
           }
       }
   }
   return false;
   
   // return true;
   // return DLMS_SOURCE_DIAGNOSTIC_AUTHENTICATION_FAILURE;
}

 

currently it shows 
`Access error : Device reports a undefined object.`

i tried multiple times before, it either give me 

`Segmentation fault`

or

gurux.dlms.server.bin: src/GXBytebuffer.cpp:111: void CGXByteBuffer::SetPosition(long unsigned int): Assertion `!(value > m_Size)' failed.

 

I tried to follow the structure of C code. please show me where i did wrong. is it the object declaration? perhaps the usage or the place of code is wrong? can you provide minimal example on how to do this in cpp?

Thank you.

Regards,

jack

Profile picture for user Kurumi

Kurumi

3 months 3 weeks ago

Hi, You don't need to add…

Hi,

You don't need to add CGXCipher if you are only implementing GMAC authentication.
CGXCipher is used with secure connections.

It's possible that the small example will be done in August after the summer holiday season is over in Finland.

BR,
Mikko

Profile picture for user jack 001

jack 001

3 months 3 weeks ago

Hi Mikko I'm looking forward…

Hi Mikko

I'm looking forward for new example to be done, thank you for that.
I actually plan to have at least a connection with low authentication (password) and a connection with HighGMAC authentication, i presume that's what all of those headers file in include used for (GXDLMSServerLN, GXDLMSServerLN_47, GXDLMSServerSN, GXDLMSServerSN_47), am i right?

Profile picture for user Kurumi

Kurumi

3 months 2 weeks ago

Hi, GXDLMSServerLN…

Hi,

GXDLMSServerLN implements a Logical Name meter that uses HDLC framing.
GXDLMSServerSN implements a Short Name meter that uses HDLC framing.
GXDLMSServerLN_47 implements a Logical Name meter that uses WRAPPER framing.
GXDLMSServerSN_47 implements a Short Name meter that uses WRAPPER framing.

HDLC is used with serial port connections and WRAPPER with TCP/IP connections.

BR,
Mikko

Profile picture for user jack 001

jack 001

3 months 2 weeks ago

Hi Mikko, thank you, it's…

Hi Mikko, thank you, it's clear now
So if i want to add different security, what would be the best place for the code? can I just make another header file? or should i just put it inside the CGXDLMSBase::Init ?

Regards,
jack

Profile picture for user Kurumi

Kurumi

3 months 2 weeks ago

Hi, If you want to add a new…

Hi,

If you want to add a new security, you need to add your own association for that. You can do that in CGXDLMSBase::Init.

BR,
Mikko

Profile picture for user jack 001

jack 001

3 months 2 weeks ago

Hi Mikko, thank you for the…

Hi Mikko, thank you for the prompt response. I will try and report back to you.

Regards
jack

Profile picture for user jack 001

jack 001

3 months ago

Hi Mikko, how're you doing?…

Hi Mikko, how're you doing?
I have tried adding highGMAC auth and a separate association, but haven't managed to do it. Will there be a new example of this in CPP?

Thank you
jack

Profile picture for user Kurumi

Kurumi

3 months ago

Hi Jack, Customers are…

Hi Jack,

Customers are keeping us busy, but this is released at the end of this month.

BR,
Mikko

Profile picture for user jack 001

jack 001

3 months ago

Hi Mikko, thank you for the…

Hi Mikko, thank you for the update on the schedule. In the meantime, i'll try again and report back my result here.

Regards
jack

Profile picture for user jack 001

jack 001

2 months 1 week ago

Hi Mikko, hope you have a…

Hi Mikko, hope you have a good day. Is there any update regarding HighGMAC example in C++?

Regards,
jack

  • Create new account
  • Reset your password

Hire Us!

Latest Releases

  • Wed, 10/29/2025 - 08:51
    gurux.dlms.c 9.0.2510.2901
  • Thu, 10/16/2025 - 09:59
    gurux.dlms.java 4.0.83
  • Wed, 10/08/2025 - 10:21
    gurux.dlms.c 9.0.2510.0801
  • Fri, 09/26/2025 - 10:02
    gurux.dlms.cpp 9.0.2509.2601
  • Fri, 09/26/2025 - 09:45
    gurux.dlms.c 9.0.2509.2601

New forum topics

  • How to get/convert user readable format data from readRowsByRange
  • Insufficient memory to continue the execution of the program.
  • The client instance code failed to connect to the electricity meter for authentication
  • Unable to Release Request when closing connection with meter.
  • Failed to receive reply from the device in given time.
More
RSS feed
Privacy FAQ GXDN Issues Contact
Follow Gurux on Twitter Follow Gurux on Linkedin