
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_cryptographyECDH-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)
- 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.
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.
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.
//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.