Getting started

Read basic information from Gurux.DLMS component before you start to create secure DLMS client.
In this document I'll go through the encryption superficially and purpose is explain what information is needed to make secure connection between client and the meter.
Note! All meters do not support secured connections.

Secure level

The secure level tells how data is secured. Data can be secured using three different ways: Authentication only, Encryption only, and Authentication and Encryption. In the authentication, the authentication tag is counted for sent data. If data is changed, the authentication tag is not valid and an error occurred. If encryption is used, sent data is encrypted.

Security Suites

In DLMS there are three different kinds of ways to secure connection between the client and the meter.
  • AES-GCM-128 AES-GCM-128
  • ECDH-ECDSAAES-GCM-128SHA-256
  • ECDH-ECDSAAES-GCM-256SHA-384

FAQ

How to know what security suites are supported?

You can check this from the Security Setup SecuritySuite attribute. Security Setup version 0 supports only AES-GCM-128 AES-GCM-128. If there is no Security Suite object available secured connections usually are not supported. Some meter manufacturers are supporting secured connections but they have not implemented the Security Suite interface.

What is the difference between glo_* and ded_messages?

glo_* messages are ciphered using block cipher key. Ded-messages are ciphered using a dedicated key. Gurux libraries use ded_messages if a dedicated key is set. If the dedicated key is not set, glo_messages are used automatically.

What is general protection?

General protection defines what kind of messages are used to cipher the messages. General protection is used if General protection conformance bit is set.

Deciphering failed -error

Deciphering failed -error is received if the connection is trying to establish without ciphering and meter expects it. The expected ciphering level is set to the Security setup Policy property. If you get this error, change the Security to the expected one. In GXDLMSDirector you can find this from the "Secured Connections" -tab. You might get this error also if one of the ciphering keys is wrong.

Invocation Counter is invalid-error

Some meters expect that expected invacation counter value is used. Invacation counter value is increased every time when ciphered operation (Get/Set/Action or Read/Write) is executed. If this error is received you need to read frame counter data object from the meter before establish the connection.
Note! There might be several frame counter objects.

Symmetric cryptography

AES-GCM-128 AES-GCM-128

AES-GCM-128 AES-GCM-128 AKA Security Suite 0 is the most used way to secure connection between the client and the meter. Security Suite 0 uses symmetric cryptography. In Symmetric cryptography send data is secured using GMAC ciphering. In Symmetric cryptography following information is needed to encrypt the data:
  • Used secure level
  • System title
  • Block cipher key
  • Authentication key
  • Invocation Counter
For decrypting only Block cipher key and is needed. In Italy standard also system title is needed because it's not part of the message.

Used secure level

The client decides how the data is encrypted when the connection is established.

System title

System title is a 8 octets value that identifies the meter. The first 3 octets of the system title hold the three-letters manufacturer ID (FLAG ID). The remainder of the system title holds a serial number of the meter.

Block cipher key

Block cipher key is a 16 octets value that defines the secret encryption key. This information is needed from the meter manufacturer and each manufacturer has its own key. Gurux libraries are using default DLMS standard key: 000102030405060708090A0B0C0D0E0F. You need to change this to the same what meter manufacturer is using.

Authentication key

The authentication key is a 16 octet value that is used in AAD(Additional Authentication Data). This information is needed from the meter manufacturer and each manufacturer has its own key. Gurux libraries are using default DLMS standard key: D0D1D2D3D4D5D6D7D8D9DADBDCDDDEDF. You need to change this to the same what meter manufacturer is using.

Dedicated key

The dedicated key is a 16 octet value that the client sends to the server when the connection is established. General idea is that a dedicated key can be the random value that is generated again before each connection. Some meters expect that dedicated key is a fixed value.

Invocation Counter

Invocation Counter is used to make each sent packet different. Invocation Counter is increased every time when new packet is sent. So if the same packet is sent twice encrypted data is different because of Invocation Counter. The invocation Counter is starting from number 1.
The following example shows how to initialize Security Suite 0 settings. After initialize is set all ciphering settings are done insize the library. Users do not need to do anything.
Note! If any of the settings are wrong, the meter does not reply to anything or returns an error.
GXDLMSSecureClient cl = new GXDLMSSecureClient(true, 1, 1, Authentication.NONE, null, InterfaceType.WRAPPER);
cl.getCiphering().setSecurity(Security.ENCRYPTION);
cl.getCiphering().setSystemTitle(GXCommon.hexToBytes("4D4D4D0000BC614E"));
cl.getCiphering().setBlockCipherKey(GXCommon.hexToBytes("000102030405060708090A0B0C0D0E0F"));
cl.getCiphering().setAuthenticationKey(GXCommon.hexToBytes("D0D1D2D3D4D5D6D7D8D9DADBDCDDDEDF"));
GXDLMSSecureClient cl = new GXDLMSSecureClient(true, 1, 1, Authentication.None, null, InterfaceType.Wrapper);
cl.Ciphering.Security = Security.Encryption);
cl.Ciphering.SystemTitle = GXCommon.HexToBytes("4D4D4D0000BC614E"));
cl.Ciphering.BlockCipherKey = GXCommon.HexToBytes("000102030405060708090A0B0C0D0E0F"));
cl.Ciphering.AuthenticationKey = GXCommon.HexToBytes("D0D1D2D3D4D5D6D7D8D9DADBDCDDDEDF"));
CGXByteBuffer tmp;
CGXDLMSSecureClient cl(true, 1, 1, DLMS_AUTHENTICATION_NONE, NULL, DLMS_INTERFACE_TYPE_WRAPPER);
cl.GetCiphering()->SetSecurity(DLMS_SECURITY_ENCRYPTION);
GXHelpers::HexToBytes("4D4D4D0000BC614E", tmp);
cl.GetCiphering()->SetSystemTitle(tmp);
GXHelpers::HexToBytes("000102030405060708090A0B0C0D0E0F", tmp);
cl.GetCiphering()->SetBlockCipherKey(tmp);
GXHelpers::HexToBytes("D0D1D2D3D4D5D6D7D8D9DADBDCDDDEDF", tmp);
cl.GetCiphering()->SetAuthenticationKey(tmp);
connection con;
con_init(&con, 1);
cl_init(&con.settings, 1, 1, 1, DLMS_AUTHENTICATION_NONE, NULL, DLMS_INTERFACE_TYPE_WRAPPER);
con.settings.cipher.security = DLMS_SECURITY_ENCRYPTION;
bb_clear(&con.settings.cipher.systemTitle);
bb_clear(&con.settings.cipher.blockCipherKey);
bb_clear(&con.settings.cipher.authenticationKey);
bb_addHexString(&con.settings.cipher.systemTitle, "4D4D4D0000BC614E");
bb_addHexString(&con.settings.cipher.blockCipherKey, "000102030405060708090A0B0C0D0E0F");
bb_addHexString(&con.settings.cipher.authenticationKey, "D0D1D2D3D4D5D6D7D8D9DADBDCDDDEDF");

Asymmetric cryptography (Public key cryptography)

ECDH-ECDSAAES-GCM-128SHA-256

ECDH-ECDSAAES-GCM-128SHA-256 AKA Security Suite 1 is using asymmetric cryptography (Public key cryptography). In Security Suite 1 parties have Public and Private key. More information from this can be found from Wikipedia.

ECDH-ECDSAAES-GCM-256SHA-384

ECDH-ECDSAAES-GCM-256SHA-384 AKA Security Suite 2 is using asymmetric cryptography (Public key cryptography). In Security Suite 2 parties have Public and Private key. More information from this can be found from Wikipedia. There are two possibilities to establish asymmetric cryptography connection to the meter.
  • Using Agreement key (Static-Unified Model)
  • Using Agreement and Signing key (One-pass Diffie-Hellman)
In asymmetric cryptography following information is needed to make connection to the meter:
  • Used secure level
  • Used security suite
  • Authentication key
  • Private and public Agreement key for the client
  • Meter's public Agreement key certificate
  • Client's system title
  • Meter's system title
GXDLMSSecureClient cl = new GXDLMSSecureClient(true, 1, 1, Authentication.NONE, null, InterfaceType.WRAPPER);
cl.getCiphering().setSecurity(Security.ENCRYPTION);
cl.setSecuritySuite(SecuritySuite.ECDH_ECDSA_AES_GCM_128_SHA_256);
cl.getCiphering().setSystemTitle(GXCommon.hexToBytes("4D4D4D0000BC614E"));
target.getCiphering().setRecipientSystemTitle(GXCommon.hexToBytes("4D4D4D0000000001"));
cl.getCiphering().setAuthenticationKey(GXCommon.hexToBytes("D0D1D2D3D4D5D6D7D8D9DADBDCDDDEDF"));
//C# is not support this at the moment.
//ANSI C++ is not support this at the moment.
//ANSI C is not support this at the moment.

Before a connection can be established between the client and the meter there are few things to do. The first client needs to send it's certificate to the meter. This needs to be done once.
Note! There might be only one client certificate at the meter. If there are several clients reading each client must update the certificate first!
You can get a list of certificates from the meter and check is that correct using the Security Suite object.

// Generate signing keys.
Date from = new Date();
Date to = new Date(from.getTime() + 365L * 24L * 60L * 60L * 1000L);
// Create client certificate for digital signature.
GXx509Certificate certificate = GXx509Certificate
    .createSelfSignedCertificate(target.getSigningKeyPair(), from,
    to, target.getCiphering().getSystemTitle(),
    "CN=Test, O=Gurux, L=Tampere, C=FI", KeyUsage.forValue(
    (KeyUsage.KEY_AGREEMENT.getValue())));

// Send client's digital signature to the server.
ss.importCertificate(target, certificate);
//Check reply.
//C# is not support this at the moment.
//ANSI C++ is not support this at the moment.
//ANSI C is not support this at the moment.
After that meter needs to generate Public and Private key and generated public key must ask from the meter.
Note! If you are using One-pass Diffie-Hellman you will need Agreement and signing Keys. Otherwise, you need only the Agreement Key. This needs to be done once.
You can get a list of server certificates from the meter and check is that correct using Security Suite object.
// Generate Public and Private keys.
data = ss.generateKeyPair(target,
    CertificateType.KEY_AGREEMENT);
//Send to the meter and check reply.

//Get certificate of the meter.
data = ss.generateCertificate(target,
    CertificateType.KEY_AGREEMENT);
//Send to the meter and check reply. Get certificate.
info.clear();
target.getData(reply, info);
GXPkcs10 cert = new GXPkcs10((byte[]) info.getValue());
//C# is not support this at the moment.
//ANSI C++ is not support this at the moment.
//ANSI C is not support this at the moment.
Now you have a Public key certificate (PKC). Next, you need to send it to a Certificate authority (CA) or create a self-signed certificate. When this is done you send the meter's digital signature to the meter. Note! This needs to be done once.
//Create self signed certificate.
certificate = GXx509Certificate.createSelfSignedCertificate(
    server.getSigningKeyPair(), from, to, cert.getSubject(),
    "CN=Test, O=Gurux, L=Tampere, C=FI",
    KeyUsage.forValue((KeyUsage.KEY_AGREEMENT.getValue())));
// Send meter's digital signature to the meter.
data = ss.importCertificate(target, certificate);
//C# is not support this at the moment.
//ANSI C++ is not support this at the moment.
//ANSI C is not support this at the moment.

Communicating with Static-Unified Model

If you are using Static-Unified Model you can make direct connection to the meter without AARQ or AARQ messages. Just make sure that you have KeyAgreement Key Pair set and it's updated to the meter. Then set also System title for the client and server.

Communicating with One-pass Diffie-Hellman

Communicating with One-pass Diffie-Hellman is more complicated. First, you need to create Agreement Key and Signing Key and update them to the meter. When the connection is established Ephemeral keys are generated and shared secret from this. This means that the encryption key is different for each connection. Note! This is done every time after the AARQ/AARE message.
data = ss.keyAgreement(target, GlobalKeyType.UNICAST_ENCRYPTION);
info.clear();
target.getData(reply, info);
target.getSharedSecret((byte[]) info.getValue(), certificate.getPublicKey());
//C# is not support this at the moment.
//ANSI C++ is not support this at the moment.
//ANSI C is not support this at the moment.
After Ephemeral keys are generated messages are automatically secured. Thats it. If you have any questions or ideas on how to improve Gurux.DLMS component let us know or ask question in a Forum