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

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

Security Suites

In DLMS there are three different kind 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 Security Setup SecuritySuite attribute. Security Setup version 0 supports only AES-GCM-128 AES-GCM-128. If there are no Security Suite object available secured connections usually are not supported. Some meter manufacturers are supporting secured connections but they have not implemented Security Suite interface.

Symmetric cryptography

AES-GCM-128 AES-GCM-128

AES-GCM-128 AES-GCM-128 AKA Security Suite 0 is most used way to secure connection between 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:
  • Used secure level
  • System title
  • Block cipher key
  • Authentication key
  • Invocation Counter

Used secure level

The client decides how the data is encrypted when 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 secret encryption key. This information is needed from the meter manufacturer and each manufacturer has own key. Gurux libraries are using default DLMS standard key: 000102030405060708090A0B0C0D0E0F. You need to change this to same what meter manufacturer is using.

Authentication key

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

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 same packet is sent twice crypted data is different because Invocation Counter. Invocation Counter is starting from number 1.
Following example shows how to initialize Security Suite 0 settings. After initialize is set all ciphering settings are done insize the library. User do not need to do anything.
Note! If any of settings is wrong, meter do not reply anything or returns 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"));
cl.getConformance().add(Conformance.GENERAL_PROTECTION);
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"));
cl.Conformance |= Conformance.GeneralProtection;
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: https://en.wikipedia.org/wiki/Public-key_cryptography

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: https://en.wikipedia.org/wiki/Public-key_cryptography

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.
First client needs to send it's certificate to 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 certificate first!
You can get list of certificates from the meter and check is that correct using 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. Otherwice you need only Agreement Key. This needs to be done once.
You can get 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 Public key certificate (PKC). Next you need to send it to Certificate authority (CA) or create a self-signed certificate. When this is done you send 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 connection is established Ephemeral keys are gererated and shared secret from this. This means that encryption key is different for each connection. Note! This is done every time after 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 how to improve Gurux.DLMS component let us know or ask question in a Forum