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 a 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
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. At first, you need to create private and public keys and send them to the meter. This video shows how to generate private and public keys with GXDLMSDirector. There are three possibilities to establish asymmetric cryptography connection to the meter.- Using Agreement key (Static-Unified Model)
- Using Agreement and Signing key (One-pass Diffie-Hellman)
- 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"));
GXDLMSSecureClient cl = new GXDLMSSecureClient(true, 1, 1, Authentication.None, null, InterfaceType.Wrapper); cl.Ciphering().Security = Security.AuthenticationEncryption); cl.SecuritySuite = SecuritySuite.Ecdsa256; cl.Ciphering.SystemTitle = GXCommon.HexToBytes("4D4D4D0000BC614E"); target.Ciphering.RecipientSystemTitle = GXCommon.hexToBytes("4D4D4D0000000001");
//ANSI C++ is not support this at the moment.
//ANSI C is not support this at the moment.
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.
// Send client's digital signature to the server. ss.importCertificate(target, certificate); //Check reply.
// Send client's digital signature to the server. ss.ImportCertificate(target, certificate); //Check reply.
//ANSI C++ is not support this at the moment.
//ANSI C is not support this at the moment.
Note! If you are using One-pass Diffie-Hellman you will need an Agreement and signing Keys. If you are using Ephemeral Unified Model you need only the Signing key and with Static-Unified Model, 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());
// Generate Public and Private keys. data = ss.GenerateKeyPair(target,CertificateType.KeyAgreement); //Send to the meter and check reply. //Get certificate of the meter. data = ss.GenerateCertificate(target, CertificateType.KeyAgreement); //Send to the meter and check reply. Get certificate. info.Clear(); target.GetData(reply, info); GXPkcs10 cert = new GXPkcs10((byte[]) info.Value);
//ANSI C++ is not support this at the moment.
//ANSI C is not support this at the moment.
// Send meter's digital signature to the meter. data = ss.importCertificate(target, certificate);
// Send meter's digital signature to the meter. data = ss.ImportCertificate(target, certificate);
//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());
data = ss.KeyAgreement(target, GlobalKeyType.UnicastEncryption); info.Clear(); target.GetData(reply, info); target.GetSharedSecret((byte[]) info.Value, certificate.PublicKey);
//ANSI C++ is not support this at the moment.
//ANSI C is not support this at the moment.