Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Generate OSCORE object and use it for endpoint creation #736

Closed
Closed
Show file tree
Hide file tree
Changes from 7 commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
708e734
Generate OSCORE object and use it for endpoint creation
rikard-sics Sep 12, 2019
8fc7bfc
Removed Californium dependencies from leshan-client-core
rikard-sics Sep 17, 2019
dc37bd9
Removed static initializers from Oscore class, instead use constructors
rikard-sics Sep 17, 2019
ebc728a
Use hex string manipulation method from Leshan rather than adding new
rikard-sics Sep 17, 2019
dd58e43
Renamed initialization method for OSCORE only in Security object
rikard-sics Sep 17, 2019
ecebdfa
Updated Security object xml and introduced link to OSCORE object
rikard-sics Sep 18, 2019
3e7db26
Use link from Security to find OSCORE object when creating ServerInfo
rikard-sics Sep 18, 2019
ae73ab2
Modified OSCORE object to take an instance id in its constructor
rikard-sics Sep 18, 2019
495d501
Removed OSCORE endpoint create method and added db parameter to others
rikard-sics Sep 18, 2019
6617c21
Two small fixes
rikard-sics Sep 18, 2019
a255bd6
Do not iterate to find OSCORE object in ServersInfoExtractor
rikard-sics Sep 18, 2019
3a4e777
Removed SecurityMode for OSCORE. Instead use OSCORE Security Mode link
rikard-sics Sep 18, 2019
401db2b
Set client name as client OSCORE Sender ID
rikard-sics Sep 18, 2019
a83918e
Updated print statement to use LOG instead
rikard-sics Sep 18, 2019
40213f6
Fix for clients to register using name configured in server interface
rikard-sics Sep 18, 2019
17098a7
Undid the change to isSecure method in ServerInfo
rikard-sics Sep 18, 2019
7116077
Moved creation of OSCORE endpoint to a better place
rikard-sics Sep 18, 2019
0138768
Applying Leshan Eclipse formatter to code and small comment fixes
rikard-sics Sep 19, 2019
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 @@ -12,11 +12,16 @@
*
* Contributors:
* Sierra Wireless - initial API and implementation
* Rikard Höglund (RISE SICS) - Additions to support OSCORE
*******************************************************************************/
package org.eclipse.leshan.client.californium.impl;

import java.io.IOException;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.UnknownHostException;
import java.security.PublicKey;
import java.security.cert.Certificate;
import java.security.cert.X509Certificate;
Expand All @@ -27,8 +32,13 @@
import org.eclipse.californium.core.network.CoapEndpoint;
import org.eclipse.californium.core.network.Endpoint;
import org.eclipse.californium.core.network.config.NetworkConfig;
import org.eclipse.californium.cose.AlgorithmID;
import org.eclipse.californium.cose.CoseException;
import org.eclipse.californium.elements.Connector;
import org.eclipse.californium.elements.auth.RawPublicKeyIdentity;
import org.eclipse.californium.oscore.HashMapCtxDB;
import org.eclipse.californium.oscore.OSCoreCtx;
import org.eclipse.californium.oscore.OSException;
import org.eclipse.californium.scandium.DTLSConnector;
import org.eclipse.californium.scandium.config.DtlsConnectorConfig.Builder;
import org.eclipse.californium.scandium.dtls.AlertMessage;
Expand All @@ -50,6 +60,8 @@
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.upokecenter.cbor.CBORObject;

public class CaliforniumEndpointsManager implements EndpointsManager {

private static final Logger LOG = LoggerFactory.getLogger(CaliforniumEndpointsManager.class);
Expand Down Expand Up @@ -113,6 +125,46 @@ public boolean isTrusted(RawPublicKeyIdentity id) {
}
});
serverIdentity = Identity.rpk(serverInfo.getAddress(), expectedKey);
} else if (serverInfo.secureMode == SecurityMode.OSCORE) {
System.out.println("Adding OSCORE CTX " + serverInfo.getFullUri().toASCIIString());
HashMapCtxDB db = HashMapCtxDB.getInstance(); //TODO: Do not use singleton here but give it to endpoint builder (for Cf-M16)

AlgorithmID hkdfAlg = null;
try {
hkdfAlg = AlgorithmID.FromCBOR(CBORObject.FromObject(serverInfo.hkdfAlgorithm));
} catch (CoseException e) {
LOG.error("Failed to decode OSCORE HMAC algorithm");
}

AlgorithmID aeadAlg = null;
try {
aeadAlg = AlgorithmID.FromCBOR(CBORObject.FromObject(serverInfo.aeadAlgorithm));
} catch (CoseException e) {
LOG.error("Failed to decode OSCORE AEAD algorithm");
}

try {
OSCoreCtx ctx = new OSCoreCtx(serverInfo.masterSecret, true, aeadAlg, serverInfo.senderId, serverInfo.recipientId, hkdfAlg, 32, serverInfo.masterSalt, serverInfo.idContext);
db.addContext(serverInfo.getFullUri().toASCIIString(), ctx);

// Also add the context by the IP of the server since requests may use that
String serverIP = InetAddress.getByName(serverInfo.getFullUri().getHost()).getHostAddress();
db.addContext("coap://" + serverIP, ctx);

} catch (OSException | UnknownHostException e) {
LOG.error("Failed to generate OSCORE context information");
return null;
}

if (endpointFactory != null) {
currentEndpoint = endpointFactory.createOSCoreEndpoint(localAddress, coapConfig, null, db);
} else {
CoapEndpoint.Builder builder = new CoapEndpoint.Builder();
builder.setInetSocketAddress(localAddress);
builder.setNetworkConfig(coapConfig);
currentEndpoint = builder.build();
}
serverIdentity = Identity.unsecure(serverInfo.getAddress()); //TODO: FIX?
} else if (serverInfo.secureMode == SecurityMode.X509) {
// set identity
newBuilder.setIdentity(serverInfo.privateKey, new Certificate[] { serverInfo.clientCertificate });
Expand Down Expand Up @@ -153,13 +205,15 @@ public X509Certificate[] getAcceptedIssuers() {
} else {
throw new RuntimeException("Unable to create connector : unsupported security mode");
}
if (endpointFactory != null) {
currentEndpoint = endpointFactory.createSecuredEndpoint(newBuilder.build(), coapConfig, null);
} else {
CoapEndpoint.Builder builder = new CoapEndpoint.Builder();
builder.setConnector(new DTLSConnector(newBuilder.build()));
builder.setNetworkConfig(coapConfig);
currentEndpoint = builder.build();
if (currentEndpoint == null) {
if (endpointFactory != null) {
currentEndpoint = endpointFactory.createSecuredEndpoint(newBuilder.build(), coapConfig, null);
} else {
CoapEndpoint.Builder builder = new CoapEndpoint.Builder();
builder.setConnector(new DTLSConnector(newBuilder.build()));
builder.setNetworkConfig(coapConfig);
currentEndpoint = builder.build();
}
}
} else {
if (endpointFactory != null) {
Expand Down
1 change: 1 addition & 0 deletions leshan-client-core/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ Contributors:
Sierra Wireless - initial API and implementation
Zebra Technologies - initial API and implementation
Eurotech - initial API and implementation
Rikard Höglund (RISE SICS) - Additions to support OSCORE
-->
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,26 @@
*
* Contributors:
* Sierra Wireless - initial API and implementation
* Rikard Höglund (RISE SICS)
* Rikard Höglund (RISE SICS) - Additions to support OSCORE
*
*******************************************************************************/
package org.eclipse.leshan.client.object;

import static org.eclipse.leshan.LwM2mId.OSCORE_Master_Secret;
import static org.eclipse.leshan.LwM2mId.OSCORE_Sender_ID;
import static org.eclipse.leshan.LwM2mId.OSCORE_Recipient_ID;
import static org.eclipse.leshan.LwM2mId.OSCORE_AEAD_Algorithm;
import static org.eclipse.leshan.LwM2mId.OSCORE_HMAC_Algorithm;
import static org.eclipse.leshan.LwM2mId.OSCORE_Master_Salt;

import java.util.Arrays;
import java.util.List;

import org.eclipse.leshan.client.request.ServerIdentity;
import org.eclipse.leshan.client.resource.BaseInstanceEnabler;
import org.eclipse.leshan.client.resource.LwM2mInstanceEnabler;
import org.eclipse.leshan.core.model.ObjectModel;
import org.eclipse.leshan.core.model.ResourceModel.Type;
import org.eclipse.leshan.core.node.LwM2mResource;
import org.eclipse.leshan.core.response.ReadResponse;
import org.eclipse.leshan.core.response.WriteResponse;
Expand All @@ -32,78 +44,137 @@
public class Oscore extends BaseInstanceEnabler {

private static final Logger LOG = LoggerFactory.getLogger(Security.class);

private final static List<Integer> supportedResources = Arrays.asList(OSCORE_Master_Secret,
OSCORE_Sender_ID, OSCORE_Recipient_ID, OSCORE_AEAD_Algorithm, OSCORE_HMAC_Algorithm,
OSCORE_Master_Salt);

private byte[] masterSecret;
private String masterSecret;
private String senderId;
private String recipientId;
private int aeadAlgorithm;
private int hmacAlgorithm;
private int hkdfAlgorithm;
private String masterSalt;
private String idContext;

public Oscore() {

}

public Oscore(byte[] masterSecret, String senderId, String recipientId, int aeadAlgorithm, int hmacAlgorithm) {
super();
this.masterSecret = masterSecret.clone();
/**
* Default constructor.
*/
public Oscore(String masterSecret, String senderId, String recipientId, int aeadAlgorithm, int hkdfAlgorithm, String masterSalt) {
this.masterSecret = masterSecret;
this.senderId = senderId;
this.recipientId = recipientId;
this.aeadAlgorithm = aeadAlgorithm;
this.hmacAlgorithm = hmacAlgorithm;
this.hkdfAlgorithm = hkdfAlgorithm;
this.masterSalt = masterSalt;
this.idContext = "";
}

/**
* Constructor providing some default values.
*
* aeadAlgorithm = 10; //AES_CCM_16_64_128
* hmacAlgorithm = -10; //HKDF_HMAC_SHA_256
* masterSalt = "";
*
*/
public Oscore(String masterSecret, String senderId, String recipientId) {
this(masterSecret, senderId, recipientId, 10, -10, "");
}

@Override
public WriteResponse write(ServerIdentity identity, int resourceId, LwM2mResource value) {
LOG.debug("Write on resource {}: {}", resourceId, value);
// extend
return WriteResponse.notFound();
}

@Override
public ReadResponse read(ServerIdentity identity, int resourceid) {
LOG.debug("Read on resource {}", resourceid);
// extend
return ReadResponse.notFound();
}

public byte[] getMasterSecret() {
return masterSecret;
}

public void setMasterSecret(byte[] masterSecret) {
this.masterSecret = masterSecret;
}

public String getSenderId() {
return senderId;
}

public void setSenderId(String senderId) {
this.senderId = senderId;
}

public String getRecipientId() {
return recipientId;
}

public void setRecipientId(String recipientId) {
this.recipientId = recipientId;
}
// restricted to BS server?

switch (resourceId) {

case OSCORE_Master_Secret:
if (value.getType() != Type.STRING) {
return WriteResponse.badRequest("invalid type");
}
masterSecret = (String) value.getValue();
return WriteResponse.success();

case OSCORE_Sender_ID:
if (value.getType() != Type.STRING) {
return WriteResponse.badRequest("invalid type");
}
senderId = (String) value.getValue();
return WriteResponse.success();

case OSCORE_Recipient_ID:
if (value.getType() != Type.STRING) {
return WriteResponse.badRequest("invalid type");
}
recipientId = (String) value.getValue();
return WriteResponse.success();

case OSCORE_AEAD_Algorithm:
if (value.getType() != Type.INTEGER) {
return WriteResponse.badRequest("invalid type");
}
aeadAlgorithm = ((Long) value.getValue()).intValue();
return WriteResponse.success();

case OSCORE_HMAC_Algorithm:
if (value.getType() != Type.INTEGER) {
return WriteResponse.badRequest("invalid type");
}
hkdfAlgorithm = ((Long) value.getValue()).intValue();
return WriteResponse.success();

case OSCORE_Master_Salt:
if (value.getType() != Type.STRING) {
return WriteResponse.badRequest("invalid type");
}
masterSalt = (String) value.getValue();
return WriteResponse.success();


default:
return super.write(identity, resourceId, value);
}

public int getAeadAlgorithm() {
return aeadAlgorithm;
}

public void setAeadAlgorithm(int aeadAlgorithm) {
this.aeadAlgorithm = aeadAlgorithm;
}

public int getHmacAlgorithm() {
return hmacAlgorithm;
@Override
public ReadResponse read(ServerIdentity identity, int resourceid) {
// only accessible for internal read?

switch (resourceid) {

case OSCORE_Master_Secret:
return ReadResponse.success(resourceid, masterSecret);

case OSCORE_Sender_ID:
return ReadResponse.success(resourceid, senderId);

case OSCORE_Recipient_ID:
return ReadResponse.success(resourceid, recipientId);

case OSCORE_AEAD_Algorithm:
return ReadResponse.success(resourceid, aeadAlgorithm);

case OSCORE_HMAC_Algorithm:
return ReadResponse.success(resourceid, hkdfAlgorithm);

case OSCORE_Master_Salt:
return ReadResponse.success(resourceid, masterSalt);

default:
return super.read(identity, resourceid);
}
}

public void setHmacAlgorithm(int hmacAlgorithm) {
this.hmacAlgorithm = hmacAlgorithm;
@Override
public List<Integer> getAvailableResourceIds(ObjectModel model) {
return supportedResources;
}

}
Loading