All Downloads are FREE. Search and download functionalities are using the official Maven repository.

gurux.dlms.secure.GXCiphering Maven / Gradle / Ivy

There is a newer version: 4.0.72
Show newest version
//
// --------------------------------------------------------------------------
//  Gurux Ltd
// 
//
//
// Filename:        $HeadURL$
//
// Version:         $Revision$,
//                  $Date$
//                  $Author$
//
// Copyright (c) Gurux Ltd
//
//---------------------------------------------------------------------------
//
//  DESCRIPTION
//
// This file is a part of Gurux Device Framework.
//
// Gurux Device Framework is Open Source software; you can redistribute it
// and/or modify it under the terms of the GNU General Public License 
// as published by the Free Software Foundation; version 2 of the License.
// Gurux Device Framework is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of 
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 
// See the GNU General Public License for more details.
//
// More information of Gurux products: https://www.gurux.org
//
// This code is licensed under the GNU General Public License v2. 
// Full text may be retrieved at http://www.gnu.org/licenses/gpl-2.0.txt
//---------------------------------------------------------------------------

package gurux.dlms.secure;

import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.KeyPair;
import java.security.NoSuchAlgorithmException;
import java.util.HashSet;
import java.util.Set;

import javax.crypto.BadPaddingException;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;

import gurux.dlms.GXByteBuffer;
import gurux.dlms.GXICipher;
import gurux.dlms.asn.GXx509CertificateCollection;
import gurux.dlms.enums.Security;
import gurux.dlms.enums.Signing;
import gurux.dlms.objects.enums.SecurityPolicy;
import gurux.dlms.objects.enums.SecuritySuite;

/**
 * Gurux DLMS/COSEM Transport security (Ciphering) settings.
 */
public class GXCiphering implements GXICipher {
    private Security security = Security.NONE;

    Set securityPolicy;

    private byte[] authenticationKey;
    /**
     * Dedicated key.
     */
    private byte[] dedicatedKey;

    /**
     * Certificates.
     */
    private GXx509CertificateCollection certificates;

    /**
     * Ephemeral key pair.
     */
    private KeyPair ephemeralKeyPair;

    /**
     * System title.
     */
    private byte[] systemTitle;

    /**
     * recipient system title.
     */
    private byte[] recipientSystemTitle;

    /**
     * Block cipher key.
     */
    private byte[] blockCipherKey;

    /**
     * Broadcast block cipher key.
     */
    private byte[] broadcastBlockCipherKey;

    /**
     * Invocation Counter.
     */
    private long invocationCounter = 0;

    /**
     * Used security suite.
     */
    private SecuritySuite securitySuite = SecuritySuite.SUITE_0;

    /**
     * Signing key pair.
     */
    private KeyPair signingKeyPair;

    /**
     * Client key agreement key pair.
     */
    private KeyPair keyAgreementKeyPair;

    /**
     * Used signing.
     */
    private Signing signing;

    /**
     * Transaction Id.
     */
    private byte[] transactionId;

    /**
     * TLS key pair.
     */
    KeyPair tlsKeyPair;

    /**
     * Constructor. Default values are from the Green Book.
     * 
     * @param title
     *            Used system title.
     */
    public GXCiphering(final byte[] title) {
        securityPolicy = new HashSet();
        certificates = new GXx509CertificateCollection();
        setSecurity(Security.NONE);
        setSystemTitle(title);
        setBlockCipherKey(new byte[] { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09,
                0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F });
        setAuthenticationKey(new byte[] { (byte) 0xD0, (byte) 0xD1, (byte) 0xD2, (byte) 0xD3,
                (byte) 0xD4, (byte) 0xD5, (byte) 0xD6, (byte) 0xD7, (byte) 0xD8, (byte) 0xD9,
                (byte) 0xDA, (byte) 0xDB, (byte) 0xDC, (byte) 0xDD, (byte) 0xDE, (byte) 0xDF });
        signing = Signing.NONE;
    }

    public static byte[] decrypt(final GXICipher c, final AesGcmParameter p,
            final GXByteBuffer data)
            throws InvalidKeyException, NoSuchAlgorithmException, NoSuchPaddingException,
            InvalidAlgorithmParameterException, IllegalBlockSizeException, BadPaddingException {
        byte[] tmp;
        tmp = GXSecure.decryptAesGcm(c, p, data);
        return tmp;
    }

    /**
     * Cipher PDU.
     * 
     * @param p
     *            Aes GCM Parameter.
     * @param data
     *            Plain text.
     * @return Secured data.
     * @throws NoSuchPaddingException
     *             No such padding exception.
     * @throws NoSuchAlgorithmException
     *             No such algorithm exception.
     * @throws InvalidAlgorithmParameterException
     *             Invalid algorithm parameter exception.
     * @throws InvalidKeyException
     *             Invalid key exception.
     * @throws BadPaddingException
     *             Bad padding exception.
     * @throws IllegalBlockSizeException
     *             Illegal block size exception.
     */
    public static byte[] encrypt(final AesGcmParameter p, final byte[] data)
            throws InvalidKeyException, NoSuchAlgorithmException, NoSuchPaddingException,
            InvalidAlgorithmParameterException, IllegalBlockSizeException, BadPaddingException {
        if (p.getSecurity() != Security.NONE) {
            return GXSecure.encryptAesGcm(true, p, data);
        }
        return data;
    }

    @Override
    public final void reset() {
        signing = Signing.NONE;
        setSecurity(Security.NONE);
        setInvocationCounter(0);
    }

    @Override
    public final boolean isCiphered() {
        return security != Security.NONE;
    }

    /**
     * @param value
     *            Invocation Counter.
     */
    public final void setInvocationCounter(final long value) {
        invocationCounter = value;
    }

    /**
     * @return Invocation Counter.
     */
    public final long getInvocationCounter() {
        return invocationCounter;
    }

    /**
     * @return Used security.
     */
    public final Security getSecurity() {
        return security;
    }

    /**
     * @param value
     *            Used security.
     */
    public final void setSecurity(final Security value) {
        security = value;
    }

    /**
     * @param value
     *            Used security policy.
     */
    public void setSecurityPolicy(java.util.Set value) {
        securityPolicy.addAll(value);
    }

    /**
     * @return Used security policy.
     */
    public java.util.Set getSecurityPolicy() {
        return securityPolicy;
    }

    /**
     * The SystemTitle is a 8 bytes (64 bit) value that identifies a partner of
     * the communication. First 3 bytes contains the three letters manufacturer
     * ID. The remainder of the system title holds for example a serial number.
     * 
     * @see List
     *      of manufacturer IDs.
     * @return System title.
     */
    public final byte[] getSystemTitle() {
        return systemTitle;
    }

    /**
     * @param value
     *            System title.
     */
    public final void setSystemTitle(final byte[] value) {
        if (value != null && value.length != 8) {
            throw new IllegalArgumentException("Invalid system title.");
        }
        systemTitle = value;
    }

    /**
     * @return Recipient system title.
     */
    public final byte[] getRecipientSystemTitle() {
        return recipientSystemTitle;
    }

    /**
     * @param value
     *            Recipient system title.
     */
    public final void setRecipientSystemTitle(final byte[] value) {
        if (value != null && value.length != 8) {
            throw new IllegalArgumentException("Invalid recipient system title.");
        }
        recipientSystemTitle = value;
    }

    /**
     * Each block is ciphered with this key.
     * 
     * @return Block cipher key.
     */
    public final byte[] getBlockCipherKey() {
        return blockCipherKey;
    }

    public final void setBlockCipherKey(final byte[] value) {
        if (value != null && value.length != 0
                && ((getSecuritySuite() != SecuritySuite.SUITE_2 && value.length != 16)
                        || (getSecuritySuite() == SecuritySuite.SUITE_2 && value.length != 32))) {
            throw new IllegalArgumentException("Invalid Block Cipher Key.");
        }
        blockCipherKey = value;
    }

    /**
     * @return Authentication Key is 16 bytes value.
     */
    public final byte[] getAuthenticationKey() {
        return authenticationKey;
    }

    public final void setAuthenticationKey(final byte[] value) {
        if (value != null && value.length != 0
                && ((getSecuritySuite() != SecuritySuite.SUITE_2 && value.length != 16)
                        || (getSecuritySuite() == SecuritySuite.SUITE_2 && value.length != 32))) {
            throw new IllegalArgumentException("Invalid Authentication Key.");
        }
        authenticationKey = value;
    }

    /**
     * @param value
     *            Broadcast block cipher key.
     */
    public final void setBroadcastBlockCipherKey(byte[] value) {
        if (value != null && value.length != 0
                && ((getSecuritySuite() != SecuritySuite.SUITE_2 && value.length != 16)
                        || (getSecuritySuite() == SecuritySuite.SUITE_2 && value.length != 32))) {
            throw new IllegalArgumentException("Invalid Block Cipher Key.");
        }
        broadcastBlockCipherKey = value;
    }

    /**
     * @return Broadcast block cipher key.
     */
    public final byte[] getBroadcastBlockCipherKey() {
        return broadcastBlockCipherKey;
    }

    /**
     * @return Available certificates.
     */
    public final GXx509CertificateCollection getCertificates() {
        return certificates;
    }

    /**
     * @return Ephemeral key pair.
     */
    public KeyPair getEphemeralKeyPair() {
        return ephemeralKeyPair;
    }

    /**
     * @param value
     *            Ephemeral key pair.
     */
    public void setEphemeralKeyPair(final KeyPair value) {
        ephemeralKeyPair = value;
    }

    /**
     * @return Signing key pair.
     */
    public final KeyPair getSigningKeyPair() {
        return signingKeyPair;
    }

    /**
     * @param value
     *            Signing key pair.
     */
    public final void setSigningKeyPair(final KeyPair value) {
        signingKeyPair = value;
    }

    /**
     * @return Client's key agreement key pair.
     */
    public final KeyPair getKeyAgreementKeyPair() {
        return keyAgreementKeyPair;
    }

    /**
     * @param value
     *            Client's key agreement key pair.
     */
    public final void setKeyAgreementKeyPair(final KeyPair value) {
        keyAgreementKeyPair = value;
    }

    /**
     * @return Used security suite.
     */
    public SecuritySuite getSecuritySuite() {
        return securitySuite;
    }

    /**
     * @param value
     *            Used security suite.
     */
    public void setSecuritySuite(final SecuritySuite value) {
        securitySuite = value;
    }

    /**
     * Generate GMAC password from given challenge.
     * 
     * @param challenge
     *            Client to Server or Server to Client challenge.
     * @return Generated challenge.
     * @throws NoSuchPaddingException
     *             No such padding exception.
     * @throws NoSuchAlgorithmException
     *             No such algorithm exception.
     * @throws InvalidAlgorithmParameterException
     *             Invalid algorithm parameter exception.
     * @throws InvalidKeyException
     *             Invalid key exception.
     * @throws BadPaddingException
     *             Bad padding exception.
     * @throws IllegalBlockSizeException
     *             Illegal block size exception.
     */
    public byte[] generateGmacPassword(final byte[] challenge)
            throws InvalidKeyException, IllegalBlockSizeException, BadPaddingException,
            NoSuchAlgorithmException, NoSuchPaddingException, InvalidAlgorithmParameterException {
        AesGcmParameter p =
                new AesGcmParameter(null, 0x10, Security.AUTHENTICATION, SecuritySuite.SUITE_0,
                        invocationCounter, systemTitle, blockCipherKey, authenticationKey);
        p.setType(CountType.TAG);
        GXByteBuffer bb = new GXByteBuffer();
        bb.setUInt8(0x10);
        bb.setUInt32(invocationCounter);
        bb.set(GXSecure.encryptAesGcm(true, p, challenge));
        return bb.array();
    }

    @Override
    public byte[] getDedicatedKey() {
        return dedicatedKey;
    }

    @Override
    public void setDedicatedKey(final byte[] value) {
        dedicatedKey = value;
    }

    /**
     * @return Used key agreement scheme.
     */
    @Override
    public Signing getSigning() {
        return signing;
    }

    /**
     * @param value
     *            Used key agreement scheme.
     */
    @Override
    public void setSigning(final Signing value) {
        signing = value;
    }

    @Override
    public byte[] getTransactionId() {
        return transactionId;
    }

    @Override
    public void setTransactionId(byte[] value) {
        transactionId = value;
    }

    @Override
    public KeyPair getTlsKeyPair() {
        return tlsKeyPair;
    }

    @Override
    public void setTlsKeyPair(final KeyPair value) {
        tlsKeyPair = value;
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy