Search in sources :

Example 6 with NetworkKey

use of org.openremote.agent.protocol.bluetooth.mesh.NetworkKey in project openremote by openremote.

the class BaseMeshNetwork method updateNetKey.

/**
 * Update a network key in the mesh network.
 *
 * <p>
 * Updating a NetworkKey's key value requires initiating a Key Refresh Procedure. A NetworkKey that's in use
 * would require a Key Refresh Procedure to update it's key contents. However a NetworkKey that's not in could
 * be updated without this procedure. If the key is in use, call {@link #distributeNetKey(NetworkKey, byte[])}
 * to initiate the Key Refresh Procedure.
 * </p>
 *
 * @param networkKey Network key
 * @throws IllegalArgumentException if the key is already in use
 */
public synchronized boolean updateNetKey(final NetworkKey networkKey) throws IllegalArgumentException {
    final int keyIndex = networkKey.getKeyIndex();
    final NetworkKey key = getNetKey(keyIndex);
    // This will return true only if the key index and the key are the same
    if (key.equals(networkKey)) {
        // The name might be updated so we must update the key.
        return updateMeshKey(networkKey);
    } else {
        // If the keys are not the same we check if its in use before updating the key
        if (!isKeyInUse(key)) {
            // This will return true only if the key index and the key are the same
            return updateMeshKey(networkKey);
        } else {
            throw new IllegalArgumentException("Unable to update a network key that's already in use.");
        }
    }
}
Also used : NetworkKey(org.openremote.agent.protocol.bluetooth.mesh.NetworkKey)

Example 7 with NetworkKey

use of org.openremote.agent.protocol.bluetooth.mesh.NetworkKey in project openremote by openremote.

the class BaseMeshMessageHandler method parseMeshPduNotifications.

/**
 * Parse the mesh network/proxy pdus
 * <p>
 * This method will try to network layer de-obfuscation and decryption using the available network keys
 * </p>
 *
 * @param pdu     mesh pdu that was sent
 * @param network {@link MeshNetwork}
 */
protected synchronized void parseMeshPduNotifications(final byte[] pdu, final MeshNetwork network) throws ExtendedInvalidCipherTextException {
    final List<NetworkKey> networkKeys = network.getNetKeys();
    final int ivi = ((pdu[1] & 0xFF) >>> 7) & 0x01;
    final int nid = pdu[1] & 0x7F;
    final int acceptedIvIndex = network.getIvIndex().getIvIndex();
    int ivIndex = acceptedIvIndex == 0 ? 0 : acceptedIvIndex - 1;
    int tempIvIndex = ivIndex;
    NetworkKey networkKey = null;
    SecureUtils.K2Output k2Output = null;
    byte[] networkHeader = null;
    int ctlTtl = 0;
    int ctl = 0;
    int src = 0;
    ProvisionedMeshNode node = null;
    while (tempIvIndex <= ivIndex + 1) {
        // Here we go through all the network keys and filter out network keys based on the nid.
        for (int i = 0; i < networkKeys.size(); i++) {
            networkKey = networkKeys.get(i);
            k2Output = getMatchingK2Output(networkKey, nid);
            if (k2Output != null) {
                networkHeader = deObfuscateNetworkHeader(pdu, MeshParserUtils.intToBytes(tempIvIndex), k2Output.getPrivacyKey());
                ctlTtl = networkHeader[0];
                ctl = (ctlTtl >> 7) & 0x01;
                src = MeshParserUtils.unsignedBytesToInt(networkHeader[5], networkHeader[4]);
                // Check if the src is known to the network and if found let's break
                // Note a node may not be found if there are two provisioners are operating independently without syncing the network.
                node = network.getNode(src);
                if (node != null) {
                    break;
                }
            }
        }
        // IF the node was found we can safely try to decrypt message with the network key which we found src of the message.
        if (node != null && k2Output != null) {
            final byte[] sequenceNumber = ByteBuffer.allocate(3).order(ByteOrder.BIG_ENDIAN).put(networkHeader, 1, 3).array();
            LOG.info("Sequence number of received Network PDU: " + MeshParserUtils.convert24BitsToInt(sequenceNumber));
            // TODO validate ivi
            byte[] nonce;
            try {
                final int networkPayloadLength = pdu.length - (2 + networkHeader.length);
                final byte[] transportPdu = new byte[networkPayloadLength];
                System.arraycopy(pdu, 8, transportPdu, 0, networkPayloadLength);
                final byte[] decryptedPayload;
                final MeshMessageState state;
                if (pdu[0] == MeshManagerApi.PDU_TYPE_NETWORK) {
                    nonce = createNetworkNonce((byte) ctlTtl, sequenceNumber, src, MeshParserUtils.intToBytes(tempIvIndex));
                    decryptedPayload = SecureUtils.decryptCCM(transportPdu, k2Output.getEncryptionKey(), nonce, SecureUtils.getNetMicLength(ctl));
                    state = getState(src);
                } else {
                    nonce = createProxyNonce(sequenceNumber, src, MeshParserUtils.intToBytes(tempIvIndex));
                    decryptedPayload = SecureUtils.decryptCCM(transportPdu, k2Output.getEncryptionKey(), nonce, SecureUtils.getNetMicLength(ctl));
                    state = getState(MeshAddress.UNASSIGNED_ADDRESS);
                }
                if (state != null) {
                    // TODO look in to proxy filter messages
                    ((DefaultNoOperationMessageState) state).parseMeshPdu(networkKey, node, pdu, networkHeader, decryptedPayload, tempIvIndex, sequenceNumber);
                    return;
                }
            } catch (InvalidCipherTextException ex) {
                throw new ExtendedInvalidCipherTextException(ex.getMessage(), ex.getCause(), BaseMeshMessageHandler.class.getName());
            }
        }
        tempIvIndex++;
    }
}
Also used : NetworkKey(org.openremote.agent.protocol.bluetooth.mesh.NetworkKey) InvalidCipherTextException(org.bouncycastle.crypto.InvalidCipherTextException) ExtendedInvalidCipherTextException(org.openremote.agent.protocol.bluetooth.mesh.utils.ExtendedInvalidCipherTextException) ExtendedInvalidCipherTextException(org.openremote.agent.protocol.bluetooth.mesh.utils.ExtendedInvalidCipherTextException) SecureUtils(org.openremote.agent.protocol.bluetooth.mesh.utils.SecureUtils)

Aggregations

NetworkKey (org.openremote.agent.protocol.bluetooth.mesh.NetworkKey)7 InvalidCipherTextException (org.bouncycastle.crypto.InvalidCipherTextException)1 ExtendedInvalidCipherTextException (org.openremote.agent.protocol.bluetooth.mesh.utils.ExtendedInvalidCipherTextException)1 SecureUtils (org.openremote.agent.protocol.bluetooth.mesh.utils.SecureUtils)1