Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,15 @@
import com.zsmartsystems.zigbee.dongle.ember.ezsp.EzspFrame;
import com.zsmartsystems.zigbee.dongle.ember.ezsp.EzspFrameResponse;
import com.zsmartsystems.zigbee.dongle.ember.ezsp.command.EzspAddEndpointRequest;
import com.zsmartsystems.zigbee.dongle.ember.ezsp.command.EzspExportKeyRequest;
import com.zsmartsystems.zigbee.dongle.ember.ezsp.command.EzspExportKeyResponse;
import com.zsmartsystems.zigbee.dongle.ember.ezsp.command.EzspSecManImportTransientKeyRequest;
import com.zsmartsystems.zigbee.dongle.ember.ezsp.command.EzspSecManImportTransientKeyResponse;
import com.zsmartsystems.zigbee.dongle.ember.ezsp.command.EzspSecManGetNetworkKeyInfoRequest;
import com.zsmartsystems.zigbee.dongle.ember.ezsp.command.EzspSecManGetNetworkKeyInfoResponse;
import com.zsmartsystems.zigbee.dongle.ember.ezsp.structure.EzspSecurityManagerContext;
import com.zsmartsystems.zigbee.dongle.ember.ezsp.structure.EzspSecurityManagerKeyType;
import com.zsmartsystems.zigbee.dongle.ember.ezsp.structure.EzspSecurityManagerNetworkKeyInfo;
import com.zsmartsystems.zigbee.dongle.ember.ezsp.command.EzspAddEndpointResponse;
import com.zsmartsystems.zigbee.dongle.ember.ezsp.command.EzspAddOrUpdateKeyTableEntryRequest;
import com.zsmartsystems.zigbee.dongle.ember.ezsp.command.EzspAddOrUpdateKeyTableEntryResponse;
Expand Down Expand Up @@ -454,6 +463,35 @@ public EmberStatus clearKeyTable() {
* @return the {@link EmberKeyStruct} or null on error
*/
public EmberKeyStruct getKey(EmberKeyType keyType) {
// EZSP v13+: Use SecurityManager exportKey API (legacy getKey was removed)
if (EzspFrame.getEzspVersion() >= 13) {
EzspSecurityManagerKeyType secManKeyType;
switch (keyType) {
case EMBER_CURRENT_NETWORK_KEY:
secManKeyType = EzspSecurityManagerKeyType.NETWORK;
break;
case EMBER_TRUST_CENTER_LINK_KEY:
secManKeyType = EzspSecurityManagerKeyType.TC_LINK;
break;
case EMBER_APPLICATION_LINK_KEY:
secManKeyType = EzspSecurityManagerKeyType.APP_LINK;
break;
default:
logger.debug("Unsupported key type for EZSP v13 exportKey: {}", keyType);
return null;
}
EmberKeyData keyData = secManExportKey(secManKeyType);
if (keyData == null) {
return null;
}
// Wrap EmberKeyData in an EmberKeyStruct for backwards compatibility
EmberKeyStruct keyStruct = new EmberKeyStruct();
keyStruct.setKey(keyData);
keyStruct.setType(keyType);
return keyStruct;
}

// Legacy EZSP v4-v12
EzspGetKeyRequest request = new EzspGetKeyRequest();
request.setKeyType(keyType);
EzspTransaction transaction = protocolHandler
Expand All @@ -470,6 +508,32 @@ public EmberKeyStruct getKey(EmberKeyType keyType) {
return response.getKeyStruct();
}

/**
* Exports a key using the EZSP v13+ SecurityManager API.
*
* @param keyType the {@link EzspSecurityManagerKeyType} to export
* @return the {@link EmberKeyData} or null on error
*/
public EmberKeyData secManExportKey(EzspSecurityManagerKeyType keyType) {
EzspSecurityManagerContext context = new EzspSecurityManagerContext();
context.setKeyType(keyType);
EzspExportKeyRequest request = new EzspExportKeyRequest();
request.setContext(context);
EzspTransaction transaction = protocolHandler
.sendEzspTransaction(new EzspSingleResponseTransaction(request, EzspExportKeyResponse.class));
EzspExportKeyResponse response = (EzspExportKeyResponse) transaction.getResponse();
if (response == null) {
logger.debug("No response from exportKey command");
return null;
}
logger.debug(response.toString());
if (response.getSlStatus() != 0) {
logger.debug("Error exporting key: status=0x{}", String.format("%08X", response.getSlStatus()));
return null;
}
return response.getKey();
}

/**
* Gets a Security Key based on the passed key type.
*
Expand Down Expand Up @@ -682,6 +746,28 @@ public int[] getValue(EzspValueId valueId) {
public EmberStatus addTransientLinkKey(IeeeAddress partner, ZigBeeKey transientKey) {
EmberKeyData emberKey = new EmberKeyData();
emberKey.setContents(transientKey.getValue());

// EZSP v13+: Use SecurityManager importTransientKey API
if (EzspFrame.getEzspVersion() >= 13) {
EzspSecManImportTransientKeyRequest request = new EzspSecManImportTransientKeyRequest();
request.setEui64(partner);
request.setPlaintextKey(emberKey);
EzspTransaction transaction = protocolHandler.sendEzspTransaction(
new EzspSingleResponseTransaction(request, EzspSecManImportTransientKeyResponse.class));
EzspSecManImportTransientKeyResponse response = (EzspSecManImportTransientKeyResponse) transaction
.getResponse();
if (response == null) {
return EmberStatus.UNKNOWN;
}
logger.debug(response.toString());
if (response.getSlStatus() != 0) {
logger.debug("Error importing transient key: status=0x{}", String.format("%08X", response.getSlStatus()));
return EmberStatus.EMBER_ERR_FATAL;
}
return EmberStatus.EMBER_SUCCESS;
}

// Legacy EZSP v4-v12
EzspAddTransientLinkKeyRequest request = new EzspAddTransientLinkKeyRequest();
request.setPartner(partner);
request.setTransientKey(emberKey);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,7 @@ public abstract class EzspFrame {
protected static final int FRAME_ID_ENERGY_SCAN_REQUEST = 0x9C;
protected static final int FRAME_ID_ENERGY_SCAN_RESULT_HANDLER = 0x48;
protected static final int FRAME_ID_ERASE_KEY_TABLE_ENTRY = 0x76;
protected static final int FRAME_ID_EXPORT_KEY = 0x0114;
protected static final int FRAME_ID_FIND_AND_REJOIN_NETWORK = 0x21;
protected static final int FRAME_ID_FIND_KEY_TABLE_ENTRY = 0x75;
protected static final int FRAME_ID_FORM_NETWORK = 0x1E;
Expand Down Expand Up @@ -177,6 +178,7 @@ public abstract class EzspFrame {
protected static final int FRAME_ID_INCOMING_NETWORK_STATUS_HANDLER = 0xC4;
protected static final int FRAME_ID_INCOMING_ROUTE_ERROR_HANDLER = 0x80;
protected static final int FRAME_ID_INCOMING_ROUTE_RECORD_HANDLER = 0x59;
protected static final int FRAME_ID_IMPORT_KEY = 0x0115;
protected static final int FRAME_ID_INCOMING_SENDER_EUI64_HANDLER = 0x62;
protected static final int FRAME_ID_INVALID_COMMAND = 0x58;
protected static final int FRAME_ID_JOIN_NETWORK = 0x1F;
Expand Down Expand Up @@ -221,6 +223,15 @@ public abstract class EzspFrame {
protected static final int FRAME_ID_SEND_REPLY = 0x39;
protected static final int FRAME_ID_SEND_TRUST_CENTER_LINK_KEY = 0x67;
protected static final int FRAME_ID_SEND_UNICAST = 0x34;
protected static final int FRAME_ID_SEC_MAN_CHECK_KEY_CONTEXT = 0x0110;
protected static final int FRAME_ID_SEC_MAN_EXPORT_LINK_KEY_BY_EUI = 0x010D;
protected static final int FRAME_ID_SEC_MAN_EXPORT_LINK_KEY_BY_INDEX = 0x010F;
protected static final int FRAME_ID_SEC_MAN_EXPORT_TRANSIENT_KEY_BY_EUI = 0x0113;
protected static final int FRAME_ID_SEC_MAN_EXPORT_TRANSIENT_KEY_BY_INDEX = 0x0112;
protected static final int FRAME_ID_SEC_MAN_GET_APS_KEY_INFO = 0x010C;
protected static final int FRAME_ID_SEC_MAN_GET_NETWORK_KEY_INFO = 0x0116;
protected static final int FRAME_ID_SEC_MAN_IMPORT_LINK_KEY = 0x010E;
protected static final int FRAME_ID_SEC_MAN_IMPORT_TRANSIENT_KEY = 0x0111;
protected static final int FRAME_ID_SET_ADDRESS_TABLE_REMOTE_EUI64 = 0x5C;
protected static final int FRAME_ID_SET_ADDRESS_TABLE_REMOTE_NODE_ID = 0x5D;
protected static final int FRAME_ID_SET_BINDING = 0x2B;
Expand Down Expand Up @@ -288,6 +299,7 @@ public abstract class EzspFrame {
ezspHandlerMap.put(FRAME_ID_ENERGY_SCAN_REQUEST, EzspEnergyScanRequestResponse.class);
ezspHandlerMap.put(FRAME_ID_ENERGY_SCAN_RESULT_HANDLER, EzspEnergyScanResultHandler.class);
ezspHandlerMap.put(FRAME_ID_ERASE_KEY_TABLE_ENTRY, EzspEraseKeyTableEntryResponse.class);
ezspHandlerMap.put(FRAME_ID_EXPORT_KEY, EzspExportKeyResponse.class);
ezspHandlerMap.put(FRAME_ID_FIND_AND_REJOIN_NETWORK, EzspFindAndRejoinNetworkResponse.class);
ezspHandlerMap.put(FRAME_ID_FIND_KEY_TABLE_ENTRY, EzspFindKeyTableEntryResponse.class);
ezspHandlerMap.put(FRAME_ID_FORM_NETWORK, EzspFormNetworkResponse.class);
Expand All @@ -310,6 +322,7 @@ public abstract class EzspFrame {
ezspHandlerMap.put(FRAME_ID_GET_FIRST_BEACON, EzspGetFirstBeaconResponse.class);
ezspHandlerMap.put(FRAME_ID_GET_KEY, EzspGetKeyResponse.class);
ezspHandlerMap.put(FRAME_ID_GET_KEY_TABLE_ENTRY, EzspGetKeyTableEntryResponse.class);
ezspHandlerMap.put(FRAME_ID_IMPORT_KEY, EzspImportKeyResponse.class);
ezspHandlerMap.put(FRAME_ID_GET_LIBRARY_STATUS, EzspGetLibraryStatusResponse.class);
ezspHandlerMap.put(FRAME_ID_GET_MFG_TOKEN, EzspGetMfgTokenResponse.class);
ezspHandlerMap.put(FRAME_ID_GET_MULTICAST_TABLE_ENTRY, EzspGetMulticastTableEntryResponse.class);
Expand Down Expand Up @@ -392,6 +405,15 @@ public abstract class EzspFrame {
ezspHandlerMap.put(FRAME_ID_SEND_REPLY, EzspSendReplyResponse.class);
ezspHandlerMap.put(FRAME_ID_SEND_TRUST_CENTER_LINK_KEY, EzspSendTrustCenterLinkKeyResponse.class);
ezspHandlerMap.put(FRAME_ID_SEND_UNICAST, EzspSendUnicastResponse.class);
ezspHandlerMap.put(FRAME_ID_SEC_MAN_CHECK_KEY_CONTEXT, EzspSecManCheckKeyContextResponse.class);
ezspHandlerMap.put(FRAME_ID_SEC_MAN_EXPORT_LINK_KEY_BY_EUI, EzspSecManExportLinkKeyByEuiResponse.class);
ezspHandlerMap.put(FRAME_ID_SEC_MAN_EXPORT_LINK_KEY_BY_INDEX, EzspSecManExportLinkKeyByIndexResponse.class);
ezspHandlerMap.put(FRAME_ID_SEC_MAN_EXPORT_TRANSIENT_KEY_BY_EUI, EzspSecManExportTransientKeyByEuiResponse.class);
ezspHandlerMap.put(FRAME_ID_SEC_MAN_EXPORT_TRANSIENT_KEY_BY_INDEX, EzspSecManExportTransientKeyByIndexResponse.class);
ezspHandlerMap.put(FRAME_ID_SEC_MAN_GET_APS_KEY_INFO, EzspSecManGetApsKeyInfoResponse.class);
ezspHandlerMap.put(FRAME_ID_SEC_MAN_GET_NETWORK_KEY_INFO, EzspSecManGetNetworkKeyInfoResponse.class);
ezspHandlerMap.put(FRAME_ID_SEC_MAN_IMPORT_LINK_KEY, EzspSecManImportLinkKeyResponse.class);
ezspHandlerMap.put(FRAME_ID_SEC_MAN_IMPORT_TRANSIENT_KEY, EzspSecManImportTransientKeyResponse.class);
ezspHandlerMap.put(FRAME_ID_SET_ADDRESS_TABLE_REMOTE_EUI64, EzspSetAddressTableRemoteEui64Response.class);
ezspHandlerMap.put(FRAME_ID_SET_ADDRESS_TABLE_REMOTE_NODE_ID, EzspSetAddressTableRemoteNodeIdResponse.class);
ezspHandlerMap.put(FRAME_ID_SET_BINDING, EzspSetBindingResponse.class);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
/**
* Copyright (c) 2016-2026 by the respective copyright holders.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*/
package com.zsmartsystems.zigbee.dongle.ember.ezsp.command;

import com.zsmartsystems.zigbee.dongle.ember.ezsp.EzspFrameRequest;
import com.zsmartsystems.zigbee.dongle.ember.ezsp.structure.EzspSecurityManagerContext;
import com.zsmartsystems.zigbee.dongle.ember.internal.serializer.EzspSerializer;

/**
* Class to implement the Ember EZSP command <b>exportKey</b>.
* <p>
* Exports a key from the security manager based on the provided context.
* <p>
* This class provides methods for processing EZSP commands.
* <p>
* Note that this code is autogenerated. Manual changes may be overwritten.
*
* @author Chris Jackson - Initial contribution of Java code generator
*/
public class EzspExportKeyRequest extends EzspFrameRequest {
public static final int FRAME_ID = 0x0114;

/**
* The security manager context specifying which key to export.
* <p>
* EZSP type is <i>EzspSecurityManagerContext</i> - Java type is {@link EzspSecurityManagerContext}
*/
private EzspSecurityManagerContext context;

/**
* Serialiser used to serialise to binary line data
*/
private EzspSerializer serializer;

/**
* Request constructor
*/
public EzspExportKeyRequest() {
frameId = FRAME_ID;
serializer = new EzspSerializer();
}

/**
* The security manager context specifying which key to export.
* <p>
* EZSP type is <i>EzspSecurityManagerContext</i> - Java type is {@link EzspSecurityManagerContext}
*
* @return the current context as {@link EzspSecurityManagerContext}
*/
public EzspSecurityManagerContext getContext() {
return context;
}

/**
* The security manager context specifying which key to export.
*
* @param context the context to set as {@link EzspSecurityManagerContext}
*/
public void setContext(EzspSecurityManagerContext context) {
this.context = context;
}

@Override
public int[] serialize() {
// Serialize the header
serializeHeader(serializer);

// Serialize the fields
context.serialize(serializer);
return serializer.getPayload();
}

@Override
public String toString() {
final StringBuilder builder = new StringBuilder(80);
builder.append("EzspExportKeyRequest [networkId=");
builder.append(networkId);
builder.append(", context=");
builder.append(context);
builder.append(']');
return builder.toString();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
/**
* Copyright (c) 2016-2026 by the respective copyright holders.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*/
package com.zsmartsystems.zigbee.dongle.ember.ezsp.command;

import com.zsmartsystems.zigbee.dongle.ember.ezsp.EzspFrameResponse;
import com.zsmartsystems.zigbee.dongle.ember.ezsp.structure.EmberKeyData;

/**
* Class to implement the Ember EZSP command <b>exportKey</b>.
* <p>
* Exports a key from the security manager based on the provided context.
* <p>
* This class provides methods for processing EZSP commands.
* <p>
* Note that this code is autogenerated. Manual changes may be overwritten.
*
* @author Chris Jackson - Initial contribution of Java code generator
*/
public class EzspExportKeyResponse extends EzspFrameResponse {
public static final int FRAME_ID = 0x0114;

/**
* The success or failure code of the operation.
* <p>
* EZSP type is <i>sl_status_t</i> - Java type is {@link int}
*/
private int slStatus;

/**
* The exported key data.
* <p>
* EZSP type is <i>EmberKeyData</i> - Java type is {@link EmberKeyData}
*/
private EmberKeyData key;

/**
* Response and Handler constructor
*/
public EzspExportKeyResponse(int[] inputBuffer) {
// Super creates deserializer and reads header fields
super(inputBuffer);

// Deserialize the fields
slStatus = deserializer.deserializeUInt32();
key = deserializer.deserializeEmberKeyData();
}

/**
* The success or failure code of the operation.
* <p>
* EZSP type is <i>sl_status_t</i> - Java type is {@link int}
*
* @return the current slStatus as {@link int}
*/
public int getSlStatus() {
return slStatus;
}

/**
* The success or failure code of the operation.
*
* @param slStatus the slStatus to set as {@link int}
*/
public void setSlStatus(int slStatus) {
this.slStatus = slStatus;
}

/**
* The exported key data.
* <p>
* EZSP type is <i>EmberKeyData</i> - Java type is {@link EmberKeyData}
*
* @return the current key as {@link EmberKeyData}
*/
public EmberKeyData getKey() {
return key;
}

/**
* The exported key data.
*
* @param key the key to set as {@link EmberKeyData}
*/
public void setKey(EmberKeyData key) {
this.key = key;
}

@Override
public String toString() {
final StringBuilder builder = new StringBuilder(96);
builder.append("EzspExportKeyResponse [networkId=");
builder.append(networkId);
builder.append(", slStatus=");
builder.append(String.format("%08X", slStatus));
builder.append(", key=");
builder.append(key);
builder.append(']');
return builder.toString();
}
}
Loading
Loading