From 3a7bdee01be45ab759aa67ba5b38a8b3ddea5828 Mon Sep 17 00:00:00 2001 From: Julien Vermillard Date: Mon, 4 Aug 2014 14:39:35 +0200 Subject: [PATCH] bumped the version of the scandium fork --- .../java/leshan/server/lwm2m/LwM2mServer.java | 7 +- .../californium/scandium/DTLSConnector.java | 144 +++++++------ .../scandium/DTLSConnectorConfig.java | 160 +++++++++++++++ .../scandium/dtls/ClientHandshaker.java | 72 +++---- .../scandium/dtls/ClientHello.java | 8 +- .../californium/scandium/dtls/Handshaker.java | 62 ++---- .../dtls/ResumingClientHandshaker.java | 7 +- .../dtls/ResumingServerHandshaker.java | 8 +- .../scandium/dtls/ServerHandshaker.java | 56 ++--- .../dtls/cfg/ClientConnectorConfig.java | 45 ++++ .../dtls/cfg/ServerConnectorConfig.java | 41 ++++ .../dtls/pskstore/InMemoryPskStore.java | 2 +- .../scandium/dtls/pskstore/PskStore.java | 7 +- .../scandium/examples/ExampleDTLSClient.java | 86 -------- .../scandium/examples/ExampleDTLSServer.java | 97 --------- .../scandium/util/ScProperties.java | 192 ------------------ 16 files changed, 415 insertions(+), 579 deletions(-) create mode 100644 leshan-core/src/main/java/org/eclipse/californium/scandium/DTLSConnectorConfig.java create mode 100644 leshan-core/src/main/java/org/eclipse/californium/scandium/dtls/cfg/ClientConnectorConfig.java create mode 100644 leshan-core/src/main/java/org/eclipse/californium/scandium/dtls/cfg/ServerConnectorConfig.java delete mode 100644 leshan-core/src/main/java/org/eclipse/californium/scandium/examples/ExampleDTLSClient.java delete mode 100644 leshan-core/src/main/java/org/eclipse/californium/scandium/examples/ExampleDTLSServer.java delete mode 100644 leshan-core/src/main/java/org/eclipse/californium/scandium/util/ScProperties.java diff --git a/leshan-core/src/main/java/leshan/server/lwm2m/LwM2mServer.java b/leshan-core/src/main/java/leshan/server/lwm2m/LwM2mServer.java index 4cc00e4a..e79a590e 100644 --- a/leshan-core/src/main/java/leshan/server/lwm2m/LwM2mServer.java +++ b/leshan-core/src/main/java/leshan/server/lwm2m/LwM2mServer.java @@ -40,8 +40,8 @@ import leshan.server.lwm2m.observation.ObservationRegistry; import leshan.server.lwm2m.resource.RegisterResource; import leshan.server.lwm2m.security.SecureEndpoint; -import leshan.server.lwm2m.security.SecurityStore; import leshan.server.lwm2m.security.SecurityRegistry; +import leshan.server.lwm2m.security.SecurityStore; import org.apache.commons.lang.Validate; import org.eclipse.californium.scandium.DTLSConnector; @@ -131,7 +131,10 @@ public LwM2mServer(InetSocketAddress localAddress, InetSocketAddress localAddres securityRegistry = new SecurityRegistry(); } - Endpoint secureEndpoint = new SecureEndpoint(new DTLSConnector(localAddressSecure, securityRegistry)); + DTLSConnector connector = new DTLSConnector(localAddressSecure, null); + connector.getConfig().setServerPsk(securityRegistry); + + Endpoint secureEndpoint = new SecureEndpoint(connector); coapServer.addEndpoint(secureEndpoint); // define /rd resource diff --git a/leshan-core/src/main/java/org/eclipse/californium/scandium/DTLSConnector.java b/leshan-core/src/main/java/org/eclipse/californium/scandium/DTLSConnector.java index 1173324f..b98bfbc7 100644 --- a/leshan-core/src/main/java/org/eclipse/californium/scandium/DTLSConnector.java +++ b/leshan-core/src/main/java/org/eclipse/californium/scandium/DTLSConnector.java @@ -13,14 +13,15 @@ * Contributors: * Matthias Kovatsch - creator and main architect * Stefan Jucker - DTLS implementation + * Julien Vermillard - Sierra Wireless ******************************************************************************/ package org.eclipse.californium.scandium; -import java.io.File; import java.io.IOException; import java.net.DatagramPacket; import java.net.DatagramSocket; import java.net.InetSocketAddress; +import java.security.cert.Certificate; import java.util.ArrayList; import java.util.Arrays; import java.util.List; @@ -51,36 +52,25 @@ import org.eclipse.californium.scandium.dtls.ResumingServerHandshaker; import org.eclipse.californium.scandium.dtls.ServerHandshaker; import org.eclipse.californium.scandium.dtls.ServerHello; -import org.eclipse.californium.scandium.dtls.pskstore.PskStore; import org.eclipse.californium.scandium.util.ByteArrayUtils; -import org.eclipse.californium.scandium.util.ScProperties; +import ch.ethz.inf.vs.elements.Connector; import ch.ethz.inf.vs.elements.ConnectorBase; import ch.ethz.inf.vs.elements.RawData; +/** + * A {@link Connector} implementation for securing the inner datagrams using the DTLS standard. + * + */ public class DTLSConnector extends ConnectorBase { - /* * Note: DTLSConnector can also implement the interface Connector instead of extending ConnectorBase */ private final static Logger LOGGER = Logger.getLogger(DTLSConnector.class.getCanonicalName()); - public static final String KEY_STORE_LOCATION = ScProperties.std.getProperty("KEY_STORE_LOCATION".replace("/", - File.pathSeparator)); - public static final String TRUST_STORE_LOCATION = ScProperties.std.getProperty("TRUST_STORE_LOCATION".replace("/", - File.pathSeparator)); - - private int maxFragmentLength = ScProperties.std.getInt("MAX_FRAGMENT_LENGTH"); - - /** The overhead for the record header (13 bytes) and the handshake header (12 bytes) is 25 bytes */ - private int maxPayloadSize = maxFragmentLength + 25; - - /** The initial timer value for retransmission; rfc6347, section: 4.2.4.1 */ - private int retransmission_timeout = ScProperties.std.getInt("RETRANSMISSION_TIMEOUT"); - - /** Maximal number of retransmissions before the attempt to transmit a message is canceled */ - private int max_retransmit = ScProperties.std.getInt("MAX_RETRANSMIT"); + /** all the configuration options for the DTLS connector */ + private final DTLSConnectorConfig config = new DTLSConnectorConfig(this); private final InetSocketAddress address; @@ -98,19 +88,19 @@ public class DTLSConnector extends ConnectorBase { /** Storing flights according to peer-addresses. */ private Map flights = new ConcurrentHashMap(); - /** Storage for the pre-shared keys */ - private final PskStore pskStore; + /** root authorities certificates */ + private final Certificate[] rootCerts; /** * Create a DTLS connector. * - * @param address the address to binf - * @param pskStore the storage for pre-shared keys + * @param address the address to bind + * @param rootCertificates list of trusted self-signed root certificates */ - public DTLSConnector(InetSocketAddress address, PskStore pskStore) { + public DTLSConnector(InetSocketAddress address, Certificate[] rootCertificates) { super(address); this.address = address; - this.pskStore = pskStore; + this.rootCerts = rootCertificates; } /** @@ -128,30 +118,38 @@ public void close() { * @param peerAddress the remote endpoint of the session to close */ public void close(InetSocketAddress peerAddress) { - DTLSSession session = dtlsSessions.get(addressToKey(peerAddress)); + String addrKey = addressToKey(peerAddress); + try { + DTLSSession session = dtlsSessions.get(addrKey); - if (session != null) { - DTLSMessage closeNotify = new AlertMessage(AlertLevel.WARNING, AlertDescription.CLOSE_NOTIFY); + if (session != null) { + DTLSMessage closeNotify = new AlertMessage(AlertLevel.WARNING, AlertDescription.CLOSE_NOTIFY); - DTLSFlight flight = new DTLSFlight(); - flight.addMessage(new Record(ContentType.ALERT, session.getWriteEpoch(), session.getSequenceNumber(), - closeNotify, session)); - flight.setRetransmissionNeeded(false); + DTLSFlight flight = new DTLSFlight(); + flight.addMessage(new Record(ContentType.ALERT, session.getWriteEpoch(), session.getSequenceNumber(), + closeNotify, session)); + flight.setRetransmissionNeeded(false); - cancelPreviousFlight(peerAddress); + cancelPreviousFlight(peerAddress); - flight.setPeerAddress(peerAddress); - flight.setSession(session); + flight.setPeerAddress(peerAddress); + flight.setSession(session); - if (LOGGER.isLoggable(Level.FINE)) { - LOGGER.fine("Sending CLOSE_NOTIFY to " + peerAddress.toString()); - } + if (LOGGER.isLoggable(Level.FINE)) { + LOGGER.fine("Sending CLOSE_NOTIFY to " + peerAddress.toString()); + } - sendFlight(flight); - } else { - if (LOGGER.isLoggable(Level.WARNING)) { - LOGGER.warning("Session to close not found: " + peerAddress.toString()); + sendFlight(flight); + } else { + if (LOGGER.isLoggable(Level.WARNING)) { + LOGGER.warning("Session to close not found: " + peerAddress.toString()); + } } + } finally { + // clear sessions + dtlsSessions.remove(addrKey); + handshakers.remove(addrKey); + flights.remove(addrKey); } } @@ -174,7 +172,7 @@ public synchronized void stop() { // TODO: We should not return null @Override protected RawData receiveNext() throws Exception { - byte[] buffer = new byte[maxPayloadSize]; + byte[] buffer = new byte[config.getMaxPayloadSize()]; DatagramPacket packet = new DatagramPacket(buffer, buffer.length); socket.receive(packet); @@ -293,8 +291,13 @@ protected RawData receiveNext() throws Exception { LOGGER.info("Created new session as client with peer: " + peerAddress.toString()); } } - handshaker = new ClientHandshaker(peerAddress, null, session, pskStore); + ; + handshaker = new ClientHandshaker(peerAddress, null, session, rootCerts, + config.clientConfig); + handshaker.setMaxFragmentLength(config.getMaxFragmentLength()); + handshakers.put(addressToKey(peerAddress), handshaker); + if (LOGGER.isLoggable(Level.FINEST)) { LOGGER.finest("Stored re-handshaker: " + handshaker.toString() + " for " + peerAddress.toString()); @@ -323,9 +326,12 @@ protected RawData receiveNext() throws Exception { if (LOGGER.isLoggable(Level.INFO)) { LOGGER.info("Created new session as server with peer: " + peerAddress.toString()); } - handshaker = new ServerHandshaker(peerAddress, session, pskStore); + handshaker = new ServerHandshaker(peerAddress, session, rootCerts, config.serverConfig); + handshaker.setMaxFragmentLength(config.getMaxFragmentLength()); } else { - handshaker = new ResumingServerHandshaker(peerAddress, session, pskStore); + handshaker = new ResumingServerHandshaker(peerAddress, session, rootCerts, + config.serverConfig); + handshaker.setMaxFragmentLength(config.getMaxFragmentLength()); } handshakers.put(addressToKey(peerAddress), handshaker); if (LOGGER.isLoggable(Level.FINEST)) { @@ -386,7 +392,9 @@ protected RawData receiveNext() throws Exception { AlertMessage alert; if (e instanceof HandshakeException) { alert = ((HandshakeException) e).getAlert(); - LOGGER.severe("Handshake Exception (" + peerAddress.toString() + "): " + e.getMessage()); + LOGGER.severe("Handshake Exception (" + peerAddress.toString() + "): " + e.getMessage() + + " we close the session"); + close(session.getPeer()); } else { alert = new AlertMessage(AlertLevel.FATAL, AlertDescription.HANDSHAKE_FAILURE); LOGGER.log(Level.SEVERE, "Unknown Exception (" + peerAddress + ").", e); @@ -430,7 +438,8 @@ protected void sendNext(RawData message) throws Exception { // start fresh handshake session = new DTLSSession(peerAddress, true); dtlsSessions.put(addressToKey(peerAddress), session); - handshaker = new ClientHandshaker(peerAddress, message, session, pskStore); + handshaker = new ClientHandshaker(peerAddress, message, session, rootCerts, config.clientConfig); + handshaker.setMaxFragmentLength(config.getMaxFragmentLength()); } else { @@ -442,8 +451,10 @@ protected void sendNext(RawData message) throws Exception { } else { // try resuming session - handshaker = new ResumingClientHandshaker(peerAddress, message, session, pskStore); + handshaker = new ResumingClientHandshaker(peerAddress, message, session, rootCerts, config.clientConfig); + handshaker.setMaxFragmentLength(config.getMaxFragmentLength()); } + } DTLSFlight flight = new DTLSFlight(); @@ -470,6 +481,19 @@ protected void sendNext(RawData message) throws Exception { sendFlight(flight); } + /** + * Returns the {@link DTLSSession} related to the given peer address. + * + * @param address the peer address + * @return the {@link DTLSSession} or null if no session found. + */ + public DTLSSession getSessionByAddress(InetSocketAddress address) { + if (address == null) { + return null; + } + return dtlsSessions.get(addressToKey(address)); + } + /** * Searches through all stored sessions and returns that session which matches the session identifier or * null if no such session available. This method is used when the server receives a @@ -512,19 +536,6 @@ private DTLSSession getSessionByIdentifier(byte[] sessionID) { return null; } - /** - * Returns the {@link DTLSSession} related to the given peer address. - * - * @param address the peer address - * @return the {@link DTLSSession} or null if no session found. - */ - public DTLSSession getSessionByAddress(InetSocketAddress address) { - if (address == null) { - return null; - } - return dtlsSessions.get(addressToKey(address)); - } - private void sendFlight(DTLSFlight flight) { byte[] payload = new byte[] {}; @@ -539,7 +550,7 @@ private void sendFlight(DTLSFlight flight) { } byte[] recordBytes = record.toByteArray(); - if (payload.length + recordBytes.length > maxPayloadSize) { + if (payload.length + recordBytes.length > config.getMaxPayloadSize()) { // can't add the next record, send current payload as datagram DatagramPacket datagram = new DatagramPacket(payload, payload.length, flight.getPeerAddress() .getAddress(), flight.getPeerAddress().getPort()); @@ -568,7 +579,7 @@ private void sendFlight(DTLSFlight flight) { private void handleTimeout(DTLSFlight flight) { // set DTLS retransmission maximum - final int max = max_retransmit; + final int max = config.getMaxRetransmit(); // check if limit of retransmissions reached if (flight.getTries() < max) { @@ -599,7 +610,7 @@ private void scheduleRetransmission(DTLSFlight flight) { // calculate timeout using exponential back-off if (flight.getTimeout() == 0) { // use initial timeout - flight.setTimeout(retransmission_timeout); + flight.setTimeout(config.getRetransmissionTimeout()); } else { // double timeout flight.incrementTimeout(); @@ -654,4 +665,7 @@ private String addressToKey(InetSocketAddress address) { return address.toString().split("/")[1]; } + public DTLSConnectorConfig getConfig() { + return config; + } } diff --git a/leshan-core/src/main/java/org/eclipse/californium/scandium/DTLSConnectorConfig.java b/leshan-core/src/main/java/org/eclipse/californium/scandium/DTLSConnectorConfig.java new file mode 100644 index 00000000..e2e4fe70 --- /dev/null +++ b/leshan-core/src/main/java/org/eclipse/californium/scandium/DTLSConnectorConfig.java @@ -0,0 +1,160 @@ +/******************************************************************************* + * Copyright (c) 2014 Institute for Pervasive Computing, ETH Zurich and others. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and Eclipse Distribution License v1.0 which accompany this distribution. + * + * The Eclipse Public License is available at + * http://www.eclipse.org/legal/epl-v10.html + * and the Eclipse Distribution License is available at + * http://www.eclipse.org/org/documents/edl-v10.html. + * + * Contributors: + * Matthias Kovatsch - creator and main architect + * Stefan Jucker - DTLS implementation + * Julien Vermillard - Sierra Wireless + *******************************************************************************/ + +package org.eclipse.californium.scandium; + +import java.security.PrivateKey; +import java.security.cert.Certificate; + +import org.eclipse.californium.scandium.dtls.cfg.ClientConnectorConfig; +import org.eclipse.californium.scandium.dtls.cfg.ServerConnectorConfig; +import org.eclipse.californium.scandium.dtls.cipher.CipherSuite; +import org.eclipse.californium.scandium.dtls.pskstore.PskStore; + +/** + * A class centralizing configuration options for the DTLS connector. + */ +public class DTLSConnectorConfig { + + /** the maximum fragment size before DTLS fragmentation must be applied */ + private int maxFragmentLength = 4096; + + /** The overhead for the record header (13 bytes) and the handshake header (12 bytes) is 25 bytes */ + private int maxPayloadSize = maxFragmentLength + 25; + + /** The initial timer value for retransmission; rfc6347, section: 4.2.4.1 */ + private int retransmissionTimeout = 1000; + + /** Maximal number of retransmissions before the attempt to transmit a message is canceled */ + private int maxRetransmit = 4; + + + ClientConnectorConfig clientConfig = new ClientConnectorConfig(); + + ServerConnectorConfig serverConfig = new ServerConnectorConfig(); + + private DTLSConnector connector; + + public DTLSConnectorConfig(DTLSConnector connector) { + this.connector = connector; + } + + private void checkStarted() { + if (connector.isRunning()) { + throw new IllegalStateException("can't configure the DTLS connector, it's already started"); + } + } + + /** + * Set the Pre-shared key store for identifying the clients in PSK mode. + * @param pskStore the key store for the client keys + */ + public void setServerPsk(PskStore pskStore) { + checkStarted(); + serverConfig.pskStore = pskStore; + } + + /** + * Set the server key for raw private key or full X509 mode. + * @param key the private key identifying the server + * @param certChain the chain of certificate for the server key + */ + public void setServerPrivateKey(PrivateKey key, Certificate[] certChain) { + checkStarted(); + serverConfig.privateKey = key; + serverConfig.certChain = certChain; + } + + /** + * Does the server require clients to authenticate. + * @param requireClientAuth set to true if you require the + * clients to authenticate + */ + public void setServerRequireClientAuth(boolean requireClientAuth) { + checkStarted(); + serverConfig.requireClientAuth = requireClientAuth; + } + + /** + * Set the client identity and pre shared secret key for PSK mode. + * @param identity the advertised client identity + * @param secret the shared secret (password) + */ + public void setClientPsk(String identity, byte[] secret) { + checkStarted(); + clientConfig.pskIdentity = identity; + clientConfig.pskSecret = secret; + } + + /** + * Set the client favorite cipher suite which is going to be placed a the + * top of the advertised supported cipher suites. + * @param suite + */ + public void setClientPreferredCipherSuite(CipherSuite suite) { + checkStarted(); + clientConfig.preferredCipherSuite = suite; + } + + /** + * Set the client key for raw private key or full X509 mode. + * @param key the private key identifying the client + * @param certChain the chain of certificate for the client key + * @param sendRawKey true the client send raw public cert, false for X509 + */ + public void setClientPrivateKey(PrivateKey key, Certificate[] certChain, boolean sendRawKey) { + checkStarted(); + clientConfig.privateKey = key; + clientConfig.certChain = certChain; + clientConfig.sendRawKey = sendRawKey; + } + + // SETTER/GETTER + + public int getMaxFragmentLength() { + return maxFragmentLength; + } + + public void setMaxFragmentLength(int maxFragmentLength) { + this.maxFragmentLength = maxFragmentLength; + } + + public int getMaxPayloadSize() { + return maxPayloadSize; + } + + public void setMaxPayloadSize(int maxPayloadSize) { + this.maxPayloadSize = maxPayloadSize; + } + + public int getRetransmissionTimeout() { + return retransmissionTimeout; + } + + public void setRetransmissionTimeout(int retransmissionTimeout) { + this.retransmissionTimeout = retransmissionTimeout; + } + + public int getMaxRetransmit() { + return maxRetransmit; + } + + public void setMaxRetransmit(int maxRetransmit) { + this.maxRetransmit = maxRetransmit; + } +} diff --git a/leshan-core/src/main/java/org/eclipse/californium/scandium/dtls/ClientHandshaker.java b/leshan-core/src/main/java/org/eclipse/californium/scandium/dtls/ClientHandshaker.java index c964bc8c..4f6801f0 100644 --- a/leshan-core/src/main/java/org/eclipse/californium/scandium/dtls/ClientHandshaker.java +++ b/leshan-core/src/main/java/org/eclipse/californium/scandium/dtls/ClientHandshaker.java @@ -16,28 +16,23 @@ ******************************************************************************/ package org.eclipse.californium.scandium.dtls; -import java.io.FileInputStream; -import java.io.InputStream; import java.net.InetSocketAddress; -import java.security.KeyStore; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; -import java.security.PrivateKey; import java.security.PublicKey; import java.security.SecureRandom; +import java.security.cert.Certificate; import java.security.interfaces.ECPublicKey; import java.security.spec.ECParameterSpec; import java.util.logging.Level; -import org.eclipse.californium.scandium.DTLSConnector; import org.eclipse.californium.scandium.dtls.AlertMessage.AlertDescription; import org.eclipse.californium.scandium.dtls.AlertMessage.AlertLevel; import org.eclipse.californium.scandium.dtls.CertificateTypeExtension.CertificateType; +import org.eclipse.californium.scandium.dtls.cfg.ClientConnectorConfig; import org.eclipse.californium.scandium.dtls.cipher.CipherSuite; import org.eclipse.californium.scandium.dtls.cipher.ECDHECryptography; -import org.eclipse.californium.scandium.dtls.pskstore.PskStore; import org.eclipse.californium.scandium.util.ByteArrayUtils; -import org.eclipse.californium.scandium.util.ScProperties; import ch.ethz.inf.vs.elements.RawData; @@ -60,6 +55,18 @@ public class ClientHandshaker extends Handshaker { /** The client's hello handshake message. Store it, to add the cookie in the second flight. */ protected ClientHello clientHello = null; + /** the preferred cipher suite, to be placed first in the advertised list of supported chiper suite */ + private final CipherSuite preferredCipherSuite; + + /** the identity to use for PSK based cipher suites */ + private final String pskIdentity; + + /** the secret key to use for PSK based cipher suites */ + private final byte[] pskSecret; + + /** whether the certificate message should only contain the peer's public key or the full X.509 certificate */ + private final boolean useRawPublicKey; + /* * Store all the message which can possibly be sent by the server. We need these to compute the handshake hash. */ @@ -87,30 +94,20 @@ public class ClientHandshaker extends Handshaker { * @param session the session * @param pskStore storage for the pre-shared-keys */ - public ClientHandshaker(InetSocketAddress endpointAddress, RawData message, DTLSSession session, PskStore pskStore) { - super(endpointAddress, true, session, pskStore); + public ClientHandshaker(InetSocketAddress endpointAddress, RawData message, DTLSSession session, + Certificate[] rootCerts, ClientConnectorConfig config) { + super(endpointAddress, true, session, rootCerts); this.message = message; + this.privateKey = config.privateKey; + this.certificates = config.certChain; + this.pskIdentity = config.pskIdentity; + this.pskSecret = config.pskSecret; + this.useRawPublicKey = config.sendRawKey; + this.preferredCipherSuite = config.preferredCipherSuite; } // Methods //////////////////////////////////////////////////////// - /** - * Loads the given keyStore (location specified in Californium.properties). The keyStore must contain the private - * key and the corresponding certificate (chain). The keyStore alias is expected to be "client". - */ - protected void loadKeyStore() { - try { - KeyStore keyStore = KeyStore.getInstance("JKS"); - InputStream in = new FileInputStream(DTLSConnector.KEY_STORE_LOCATION); - keyStore.load(in, KEY_STORE_PASSWORD.toCharArray()); - - certificates = keyStore.getCertificateChain("client"); - privateKey = (PrivateKey) keyStore.getKey("client", KEY_STORE_PASSWORD.toCharArray()); - } catch (Exception e) { - LOGGER.log(Level.SEVERE, "Could not load the keystore.", e); - } - } - @Override public synchronized DTLSFlight processMessage(Record record) throws HandshakeException { DTLSFlight flight = null; @@ -334,7 +331,7 @@ private void receivedServerCertificate(CertificateMessage message) throws Handsh serverCertificate = message; serverPublicKey = serverCertificate.getPublicKey(); - serverCertificate.verifyCertificate(loadTrustedCertificates()); + serverCertificate.verifyCertificate(rootCertificates); } /** @@ -412,19 +409,14 @@ private DTLSFlight receivedServerHelloDone(ServerHelloDone message) throws Hands break; case PSK: - String identity = ScProperties.std.getProperty("PSK_IDENTITY"); - session.setPskIdentity(identity); - - clientKeyExchange = new PSKClientKeyExchange(identity); - byte[] psk = pskStore.getPsk(identity); - if (psk == null) { - AlertMessage alert = new AlertMessage(AlertLevel.FATAL, AlertDescription.HANDSHAKE_FAILURE); - throw new HandshakeException("No preshared secret found for identity: " + identity, alert); - } + session.setPskIdentity(pskIdentity); + + clientKeyExchange = new PSKClientKeyExchange(pskIdentity); + if (LOGGER.isLoggable(Level.INFO)) { - LOGGER.info("Using PSK identity: " + identity); + LOGGER.info("Using PSK identity: " + pskIdentity); } - premasterSecret = generatePremasterSecretFromPSK(psk); + premasterSecret = generatePremasterSecretFromPSK(pskSecret); generateKeys(premasterSecret); break; @@ -529,13 +521,13 @@ private DTLSFlight receivedServerHelloDone(ServerHelloDone message) throws Hands @Override public DTLSFlight getStartHandshakeMessage() { - ClientHello message = new ClientHello(maxProtocolVersion, new SecureRandom()); + ClientHello message = new ClientHello(maxProtocolVersion, new SecureRandom(), useRawPublicKey); // store client random for later calculations clientRandom = message.getRandom(); // the mandatory to implement ciphersuites, the preferred one should be first in the list - if (ScProperties.std.getStr("PREFERRED_CIPHER_SUITE").equals(CipherSuite.TLS_PSK_WITH_AES_128_CCM_8.toString())) { + if (preferredCipherSuite == CipherSuite.TLS_PSK_WITH_AES_128_CCM_8) { message.addCipherSuite(CipherSuite.TLS_PSK_WITH_AES_128_CCM_8); message.addCipherSuite(CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8); } else { diff --git a/leshan-core/src/main/java/org/eclipse/californium/scandium/dtls/ClientHello.java b/leshan-core/src/main/java/org/eclipse/californium/scandium/dtls/ClientHello.java index 0d26200a..42c724ae 100644 --- a/leshan-core/src/main/java/org/eclipse/californium/scandium/dtls/ClientHello.java +++ b/leshan-core/src/main/java/org/eclipse/californium/scandium/dtls/ClientHello.java @@ -27,7 +27,6 @@ import org.eclipse.californium.scandium.util.ByteArrayUtils; import org.eclipse.californium.scandium.util.DatagramReader; import org.eclipse.californium.scandium.util.DatagramWriter; -import org.eclipse.californium.scandium.util.ScProperties; /** @@ -95,7 +94,8 @@ public class ClientHello extends HandshakeMessage { * @param version * @param secureRandom */ - public ClientHello(ProtocolVersion version, SecureRandom secureRandom) { + public ClientHello(ProtocolVersion version, SecureRandom secureRandom, boolean useRawPublicKey) { + this.clientVersion = version; this.random = new Random(secureRandom); this.sessionId = new SessionId(new byte[] {}); @@ -117,7 +117,7 @@ public ClientHello(ProtocolVersion version, SecureRandom secureRandom) { // the certificate types the client is able to provide to the server CertificateTypeExtension clientCertificateType = new ClientCertificateTypeExtension(true); - if (ScProperties.std.getBool("USE_RAW_PUBLIC_KEY")) { + if (useRawPublicKey) { clientCertificateType.addCertificateType(CertificateType.RAW_PUBLIC_KEY); } else { // the client supports rawPublicKeys but prefers X.509 certificates @@ -130,7 +130,7 @@ public ClientHello(ProtocolVersion version, SecureRandom secureRandom) { // the type of certificates the client is able to process when provided by the server CertificateTypeExtension serverCertificateType = new ServerCertificateTypeExtension(true); - if (ScProperties.std.getBool("USE_RAW_PUBLIC_KEY")) { + if (useRawPublicKey) { serverCertificateType.addCertificateType(CertificateType.RAW_PUBLIC_KEY); serverCertificateType.addCertificateType(CertificateType.X_509); } else { diff --git a/leshan-core/src/main/java/org/eclipse/californium/scandium/dtls/Handshaker.java b/leshan-core/src/main/java/org/eclipse/californium/scandium/dtls/Handshaker.java index 039fc892..f33dc90a 100644 --- a/leshan-core/src/main/java/org/eclipse/californium/scandium/dtls/Handshaker.java +++ b/leshan-core/src/main/java/org/eclipse/californium/scandium/dtls/Handshaker.java @@ -16,10 +16,7 @@ ******************************************************************************/ package org.eclipse.californium.scandium.dtls; -import java.io.FileInputStream; -import java.io.InputStream; import java.net.InetSocketAddress; -import java.security.KeyStore; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.security.PrivateKey; @@ -40,20 +37,17 @@ import javax.crypto.spec.IvParameterSpec; import javax.crypto.spec.SecretKeySpec; -import org.eclipse.californium.scandium.DTLSConnector; import org.eclipse.californium.scandium.dtls.cipher.CipherSuite; import org.eclipse.californium.scandium.dtls.cipher.CipherSuite.KeyExchangeAlgorithm; import org.eclipse.californium.scandium.dtls.cipher.ECDHECryptography; -import org.eclipse.californium.scandium.dtls.pskstore.PskStore; import org.eclipse.californium.scandium.util.ByteArrayUtils; -import org.eclipse.californium.scandium.util.ScProperties; import ch.ethz.inf.vs.californium.coap.Message; import ch.ethz.inf.vs.elements.RawData; /** * The base class for the handshake protocol logic. Contains all the functionality and fields which is needed by all - * types of handshakers. + * types of hand-shakers. */ public abstract class Handshaker { @@ -77,10 +71,6 @@ public abstract class Handshaker { public final static int TEST_LABEL_3 = 7; - public final static String KEY_STORE_PASSWORD = "endPass"; - - private static final String TRUST_STORE_PASSWORD = "rootPass"; - // Members //////////////////////////////////////////////////////// /** @@ -153,8 +143,11 @@ public abstract class Handshaker { /** The handshaker's certificate chain. */ protected Certificate[] certificates; - /** Used to retrive pre-shared-key fro a given identity */ - protected final PskStore pskStore; + /** list of trusted self-signed root certificates */ + protected final Certificate[] rootCertificates; + + /** the maximum fragment size before DTLS fragmentation must be applied */ + private int maxFragmentLength = 4096; // Constructor //////////////////////////////////////////////////// @@ -164,13 +157,13 @@ public abstract class Handshaker { * @param isClient indicating whether this instance represents a client or a server. * @param session the session belonging to this handshake. */ - public Handshaker(InetSocketAddress peerAddress, boolean isClient, DTLSSession session, PskStore pskStore) { + public Handshaker(InetSocketAddress peerAddress, boolean isClient, DTLSSession session, + Certificate[] rootCertificates) { this.endpointAddress = peerAddress; this.isClient = isClient; this.session = session; this.queuedMessages = new HashSet(); - this.pskStore = pskStore; - loadKeyStore(); + this.rootCertificates = rootCertificates; try { this.md = MessageDigest.getInstance("SHA-256"); } catch (NoSuchAlgorithmException e) { @@ -531,7 +524,6 @@ protected List wrapMessage(DTLSMessage fragment) { byte[] messageBytes = handshakeMessage.fragmentToByteArray(); - int maxFragmentLength = ScProperties.std.getInt("MAX_FRAGMENT_LENGTH"); if (messageBytes.length > maxFragmentLength) { /* * The sender then creates N handshake messages, all with the same message_seq value as the original @@ -628,34 +620,6 @@ protected boolean processMessageNext(Record record) throws HandshakeException { } } - /** - * Loads the given keyStore (location specified in Californium.properties). The keyStore must contain the private - * key and the corresponding certificate (chain). The keyStore alias is expected to be "client". - */ - protected abstract void loadKeyStore(); - - /** - * Loads the trusted certificates. - * - * @return the trusted certificates. - */ - protected Certificate[] loadTrustedCertificates() { - Certificate[] trustedCertificates = new Certificate[1]; - - try { - KeyStore trustStore = KeyStore.getInstance("JKS"); - InputStream in = new FileInputStream(DTLSConnector.TRUST_STORE_LOCATION); - trustStore.load(in, TRUST_STORE_PASSWORD.toCharArray()); - - // TODO load multiple certificates? - trustedCertificates[0] = trustStore.getCertificate("root"); - } catch (Exception e) { - LOGGER.log(Level.SEVERE, "Could not load the trusted certificates.", e); - } - - return trustedCertificates; - } - /** * Called when a fragmented handshake message is received. Checks if all fragments already here to reassemble the * handshake message and if so, returns the whole handshake message. @@ -847,4 +811,12 @@ public void setCompressionMethod(CompressionMethod compressionMethod) { this.compressionMethod = compressionMethod; this.session.setCompressionMethod(compressionMethod); } + + public int getMaxFragmentLength() { + return maxFragmentLength; + } + + public void setMaxFragmentLength(int maxFragmentLength) { + this.maxFragmentLength = maxFragmentLength; + } } diff --git a/leshan-core/src/main/java/org/eclipse/californium/scandium/dtls/ResumingClientHandshaker.java b/leshan-core/src/main/java/org/eclipse/californium/scandium/dtls/ResumingClientHandshaker.java index 380bb109..99606373 100644 --- a/leshan-core/src/main/java/org/eclipse/californium/scandium/dtls/ResumingClientHandshaker.java +++ b/leshan-core/src/main/java/org/eclipse/californium/scandium/dtls/ResumingClientHandshaker.java @@ -19,10 +19,11 @@ import java.net.InetSocketAddress; import java.security.MessageDigest; import java.security.SecureRandom; +import java.security.cert.Certificate; import org.eclipse.californium.scandium.dtls.AlertMessage.AlertDescription; import org.eclipse.californium.scandium.dtls.AlertMessage.AlertLevel; -import org.eclipse.californium.scandium.dtls.pskstore.PskStore; +import org.eclipse.californium.scandium.dtls.cfg.ClientConnectorConfig; import ch.ethz.inf.vs.elements.RawData; @@ -36,8 +37,8 @@ public class ResumingClientHandshaker extends ClientHandshaker { // Constructor //////////////////////////////////////////////////// public ResumingClientHandshaker(InetSocketAddress endpointAddress, RawData message, DTLSSession session, - PskStore pskStore) { - super(endpointAddress, message, session, pskStore); + Certificate[] rootCerts, ClientConnectorConfig config) { + super(endpointAddress, message, session, rootCerts, config); } // Methods //////////////////////////////////////////////////////// diff --git a/leshan-core/src/main/java/org/eclipse/californium/scandium/dtls/ResumingServerHandshaker.java b/leshan-core/src/main/java/org/eclipse/californium/scandium/dtls/ResumingServerHandshaker.java index e3c567fd..8fceeb6e 100644 --- a/leshan-core/src/main/java/org/eclipse/californium/scandium/dtls/ResumingServerHandshaker.java +++ b/leshan-core/src/main/java/org/eclipse/californium/scandium/dtls/ResumingServerHandshaker.java @@ -19,10 +19,11 @@ import java.net.InetSocketAddress; import java.security.MessageDigest; import java.security.SecureRandom; +import java.security.cert.Certificate; import org.eclipse.californium.scandium.dtls.AlertMessage.AlertDescription; import org.eclipse.californium.scandium.dtls.AlertMessage.AlertLevel; -import org.eclipse.californium.scandium.dtls.pskstore.PskStore; +import org.eclipse.californium.scandium.dtls.cfg.ServerConnectorConfig; /** @@ -41,8 +42,9 @@ public class ResumingServerHandshaker extends ServerHandshaker { // Constructor //////////////////////////////////////////////////// - public ResumingServerHandshaker(InetSocketAddress endpointAddress, DTLSSession session, PskStore pskStore) { - super(endpointAddress, session, pskStore); + + public ResumingServerHandshaker(InetSocketAddress endpointAddress, DTLSSession session, Certificate[] rootCerts, ServerConnectorConfig config) { + super(endpointAddress, session, rootCerts, config); setSessionToResume(session); } diff --git a/leshan-core/src/main/java/org/eclipse/californium/scandium/dtls/ServerHandshaker.java b/leshan-core/src/main/java/org/eclipse/californium/scandium/dtls/ServerHandshaker.java index 0803043a..db6c70b0 100644 --- a/leshan-core/src/main/java/org/eclipse/californium/scandium/dtls/ServerHandshaker.java +++ b/leshan-core/src/main/java/org/eclipse/californium/scandium/dtls/ServerHandshaker.java @@ -16,21 +16,17 @@ ******************************************************************************/ package org.eclipse.californium.scandium.dtls; -import java.io.FileInputStream; -import java.io.InputStream; import java.net.InetSocketAddress; -import java.security.KeyStore; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; -import java.security.PrivateKey; import java.security.PublicKey; import java.security.SecureRandom; +import java.security.cert.Certificate; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.logging.Level; -import org.eclipse.californium.scandium.DTLSConnector; import org.eclipse.californium.scandium.dtls.AlertMessage.AlertDescription; import org.eclipse.californium.scandium.dtls.AlertMessage.AlertLevel; import org.eclipse.californium.scandium.dtls.CertificateRequest.ClientCertificateType; @@ -38,11 +34,11 @@ import org.eclipse.californium.scandium.dtls.CertificateRequest.SignatureAlgorithm; import org.eclipse.californium.scandium.dtls.CertificateTypeExtension.CertificateType; import org.eclipse.californium.scandium.dtls.SupportedPointFormatsExtension.ECPointFormat; +import org.eclipse.californium.scandium.dtls.cfg.ServerConnectorConfig; import org.eclipse.californium.scandium.dtls.cipher.CipherSuite; import org.eclipse.californium.scandium.dtls.cipher.ECDHECryptography; import org.eclipse.californium.scandium.dtls.pskstore.PskStore; import org.eclipse.californium.scandium.util.ByteArrayUtils; -import org.eclipse.californium.scandium.util.ScProperties; /** @@ -54,7 +50,7 @@ public class ServerHandshaker extends Handshaker { // Members //////////////////////////////////////////////////////// /** Is the client required to authenticate itself? */ - private boolean clientAuthenticationRequired = ScProperties.std.getBool("CLIENT_AUTHENTICATION"); + private boolean clientAuthenticationRequired = false; /** * The client's public key from its certificate (only sent when @@ -78,7 +74,10 @@ public class ServerHandshaker extends Handshaker { protected CertificateVerify certificateVerify = null; /** The client's {@link Finished} message. Mandatory. */ protected Finished clientFinished; - + + /** Used to retrive pre-shared-key from a given client identity */ + protected final PskStore pskStore; + // Constructors /////////////////////////////////////////////////// /** @@ -90,48 +89,31 @@ public class ServerHandshaker extends Handshaker { * @param pskStore * the storage for pre-shared-keys */ - public ServerHandshaker(InetSocketAddress endpointAddress, DTLSSession session, PskStore pskStore) { - super(endpointAddress, false, session,pskStore); + public ServerHandshaker(InetSocketAddress endpointAddress, DTLSSession session, Certificate[] rootCerts, ServerConnectorConfig config) { + super(endpointAddress, false, session,rootCerts); this.supportedCipherSuites = new ArrayList(); this.supportedCipherSuites.add(CipherSuite.SSL_NULL_WITH_NULL_NULL); this.supportedCipherSuites.add(CipherSuite.TLS_PSK_WITH_AES_128_CCM_8); this.supportedCipherSuites.add(CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8); + + this.pskStore = config.pskStore; + + this.privateKey = config.privateKey; + this.certificates = config.certChain; + + this.clientAuthenticationRequired = config.requireClientAuth; } // Methods //////////////////////////////////////////////////////// - /** - * Loads the given keyStore (location specified in Californium.properties). - * The keyStore must contain the private key and the corresponding - * certificate (chain). The keyStore alias is expected to be "client". - */ - protected void loadKeyStore() { - try { - KeyStore keyStore = KeyStore.getInstance("JKS"); - InputStream in = new FileInputStream(DTLSConnector.KEY_STORE_LOCATION); - keyStore.load(in, KEY_STORE_PASSWORD.toCharArray()); - - certificates = keyStore.getCertificateChain("server"); - - -// StringBuilder sb = new StringBuilder(); -// for (Certificate cert : certificates) { -// sb.append("\t\t\tCertificate: " + cert.toString() + "\n"); -// } -// LOG.log(Level.SEVERE,"*********LOADED *******: " + sb.toString(),e); - privateKey = (PrivateKey) keyStore.getKey("server", KEY_STORE_PASSWORD.toCharArray()); - } catch (Exception e) { - LOGGER.log(Level.SEVERE, "Could not load the keystore.", e); - } - } @Override public synchronized DTLSFlight processMessage(Record record) throws HandshakeException { if (lastFlight != null) { // we already sent the last flight, but the client did not receive // it, since we received its finished message again, so we - // retransmit our last fligh + // retransmit our last flight if (LOGGER.isLoggable(Level.FINER)) { LOGGER.finer("Received client's (" + endpointAddress.toString() + ") finished message again, retransmit the last flight."); } @@ -255,7 +237,7 @@ private void receivedClientCertificate(CertificateMessage message) throws Handsh } clientCertificate = message; - clientCertificate.verifyCertificate(loadTrustedCertificates()); + clientCertificate.verifyCertificate(rootCertificates); clientPublicKey = clientCertificate.getPublicKey(); handshakeMessages = ByteArrayUtils.concatenate(handshakeMessages, clientCertificate.toByteArray()); @@ -522,7 +504,7 @@ private DTLSFlight receivedClientHello(ClientHello message) throws HandshakeExce // TODO make this variable, reasonable values certificateRequest.addCertificateType(ClientCertificateType.ECDSA_SIGN); certificateRequest.addSignatureAlgorithm(new SignatureAndHashAlgorithm(signatureAndHashAlgorithm.getHash(), signatureAndHashAlgorithm.getSignature())); - certificateRequest.addCertificateAuthorities(loadTrustedCertificates()); + certificateRequest.addCertificateAuthorities(rootCertificates); flight.addMessage(wrapMessage(certificateRequest)); md.update(certificateRequest.toByteArray()); diff --git a/leshan-core/src/main/java/org/eclipse/californium/scandium/dtls/cfg/ClientConnectorConfig.java b/leshan-core/src/main/java/org/eclipse/californium/scandium/dtls/cfg/ClientConnectorConfig.java new file mode 100644 index 00000000..1e13e949 --- /dev/null +++ b/leshan-core/src/main/java/org/eclipse/californium/scandium/dtls/cfg/ClientConnectorConfig.java @@ -0,0 +1,45 @@ +/******************************************************************************* + * Copyright (c) 2014 Institute for Pervasive Computing, ETH Zurich and others. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and Eclipse Distribution License v1.0 which accompany this distribution. + * + * The Eclipse Public License is available at + * http://www.eclipse.org/legal/epl-v10.html + * and the Eclipse Distribution License is available at + * http://www.eclipse.org/org/documents/edl-v10.html. + * + * Contributors: + * Julien Vermillard - Sierra Wireless + ******************************************************************************/ +package org.eclipse.californium.scandium.dtls.cfg; + +import java.security.PrivateKey; +import java.security.cert.Certificate; + +import org.eclipse.californium.scandium.dtls.cipher.CipherSuite; + +/** + * Internal class holding the client related DTLSConnector configuration. + */ +public class ClientConnectorConfig { + + /** the identity to use for PSK mode */ + public String pskIdentity; + + /** the secret to use for PSK mode */ + public byte[] pskSecret; + + /** the server private key for RPK and X509 mode */ + public PrivateKey privateKey = null; + + /** the server certificate for RPK and X509 mode */ + public Certificate[] certChain = null; + + /** do we send only the raw key (RPK) and not the full certificate (X509)*/ + public boolean sendRawKey=true; + + /** the client favorite cipher suite */ + public CipherSuite preferredCipherSuite = CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8; +} \ No newline at end of file diff --git a/leshan-core/src/main/java/org/eclipse/californium/scandium/dtls/cfg/ServerConnectorConfig.java b/leshan-core/src/main/java/org/eclipse/californium/scandium/dtls/cfg/ServerConnectorConfig.java new file mode 100644 index 00000000..d73a19f8 --- /dev/null +++ b/leshan-core/src/main/java/org/eclipse/californium/scandium/dtls/cfg/ServerConnectorConfig.java @@ -0,0 +1,41 @@ +/******************************************************************************* + * Copyright (c) 2014 Institute for Pervasive Computing, ETH Zurich and others. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and Eclipse Distribution License v1.0 which accompany this distribution. + * + * The Eclipse Public License is available at + * http://www.eclipse.org/legal/epl-v10.html + * and the Eclipse Distribution License is available at + * http://www.eclipse.org/org/documents/edl-v10.html. + * + * Contributors: + * Julien Vermillard - Sierra Wireless + ******************************************************************************/ + +package org.eclipse.californium.scandium.dtls.cfg; + +import java.security.PrivateKey; +import java.security.cert.Certificate; + +import org.eclipse.californium.scandium.dtls.pskstore.PskStore; + +/** + * Internal class holding the server related DTLSConnector configuration. + */ +public class ServerConnectorConfig { + + /** store of the PSK for identifying client */ + public PskStore pskStore = null; + + /** do the server require the client to authenticate */ + public boolean requireClientAuth = true; + + /** the server private key for RPK and X509 mode */ + public PrivateKey privateKey = null; + + /** the server certificate for RPK and X509 mode */ + public Certificate[] certChain = null; + +} diff --git a/leshan-core/src/main/java/org/eclipse/californium/scandium/dtls/pskstore/InMemoryPskStore.java b/leshan-core/src/main/java/org/eclipse/californium/scandium/dtls/pskstore/InMemoryPskStore.java index 3cd45b24..8217d2cf 100644 --- a/leshan-core/src/main/java/org/eclipse/californium/scandium/dtls/pskstore/InMemoryPskStore.java +++ b/leshan-core/src/main/java/org/eclipse/californium/scandium/dtls/pskstore/InMemoryPskStore.java @@ -45,7 +45,7 @@ public byte[] getPsk(String identity) { * @param identity the identity associated with the key * @param key the key used to authenticate the identity */ - public void setPsk(String identity, byte[] key) { + public void setKey(String identity, byte[] key) { keys.put(identity, key); } } \ No newline at end of file diff --git a/leshan-core/src/main/java/org/eclipse/californium/scandium/dtls/pskstore/PskStore.java b/leshan-core/src/main/java/org/eclipse/californium/scandium/dtls/pskstore/PskStore.java index ceaca3e0..1a0af4e8 100644 --- a/leshan-core/src/main/java/org/eclipse/californium/scandium/dtls/pskstore/PskStore.java +++ b/leshan-core/src/main/java/org/eclipse/californium/scandium/dtls/pskstore/PskStore.java @@ -19,13 +19,12 @@ * A storage for pre-shared-key identity. */ public interface PskStore { - + /** - * Get the pre-shared key for a given identity. - * + * Get the key for a given identity. * @param identity the identity to authenticate * @return the key or null if not found */ byte[] getPsk(String identity); - + } diff --git a/leshan-core/src/main/java/org/eclipse/californium/scandium/examples/ExampleDTLSClient.java b/leshan-core/src/main/java/org/eclipse/californium/scandium/examples/ExampleDTLSClient.java deleted file mode 100644 index 061b2903..00000000 --- a/leshan-core/src/main/java/org/eclipse/californium/scandium/examples/ExampleDTLSClient.java +++ /dev/null @@ -1,86 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2014 Institute for Pervasive Computing, ETH Zurich and others. - * - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * and Eclipse Distribution License v1.0 which accompany this distribution. - * - * The Eclipse Public License is available at - * http://www.eclipse.org/legal/epl-v10.html - * and the Eclipse Distribution License is available at - * http://www.eclipse.org/org/documents/edl-v10.html. - * - * Contributors: - * Matthias Kovatsch - creator and main architect - * Stefan Jucker - DTLS implementation - ******************************************************************************/ -package org.eclipse.californium.scandium.examples; - -import java.io.IOException; -import java.net.InetAddress; -import java.net.InetSocketAddress; -import java.util.logging.Level; - -import org.eclipse.californium.scandium.DTLSConnector; -import org.eclipse.californium.scandium.ScandiumLogger; -import org.eclipse.californium.scandium.dtls.pskstore.InMemoryPskStore; -import org.eclipse.californium.scandium.dtls.pskstore.PskStore; -import org.eclipse.californium.scandium.util.ScProperties; - -import ch.ethz.inf.vs.elements.RawData; -import ch.ethz.inf.vs.elements.RawDataChannel; - -public class ExampleDTLSClient { - - static { - ScandiumLogger.initialize(); - ScandiumLogger.setLevel(Level.FINE); - } - - public static final int DEFAULT_PORT = ScProperties.std.getInt("DEFAULT_PORT"); - - private DTLSConnector dtlsConnector; - - public ExampleDTLSClient() { - PskStore pskStore = new InMemoryPskStore(); - dtlsConnector = new DTLSConnector(new InetSocketAddress(0), pskStore); - dtlsConnector.setRawDataReceiver(new RawDataChannelImpl()); - } - - public void test() { - try { - dtlsConnector.start(); - dtlsConnector.send(new RawData("HELLO WORLD".getBytes(), InetAddress.getByName("localhost"), DEFAULT_PORT)); - } catch (IOException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } - } - - private class RawDataChannelImpl implements RawDataChannel { - - // @Override - public void receiveData(final RawData raw) { - - System.out.println(new String(raw.getBytes())); - - dtlsConnector.close(new InetSocketAddress("localhost", DEFAULT_PORT)); - - // notify main thread to exit - synchronized (ExampleDTLSClient.class) { - ExampleDTLSClient.class.notify(); - } - } - } - - public static void main(String[] args) throws InterruptedException { - - ExampleDTLSClient client = new ExampleDTLSClient(); - client.test(); - - // Connector threads run as daemons so wait in main thread until handshake is done - synchronized (ExampleDTLSClient.class) { - ExampleDTLSClient.class.wait(); - } - } -} diff --git a/leshan-core/src/main/java/org/eclipse/californium/scandium/examples/ExampleDTLSServer.java b/leshan-core/src/main/java/org/eclipse/californium/scandium/examples/ExampleDTLSServer.java deleted file mode 100644 index 1446ebaf..00000000 --- a/leshan-core/src/main/java/org/eclipse/californium/scandium/examples/ExampleDTLSServer.java +++ /dev/null @@ -1,97 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2014 Institute for Pervasive Computing, ETH Zurich and others. - * - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * and Eclipse Distribution License v1.0 which accompany this distribution. - * - * The Eclipse Public License is available at - * http://www.eclipse.org/legal/epl-v10.html - * and the Eclipse Distribution License is available at - * http://www.eclipse.org/org/documents/edl-v10.html. - * - * Contributors: - * Matthias Kovatsch - creator and main architect - * Stefan Jucker - DTLS implementation - ******************************************************************************/ -package org.eclipse.californium.scandium.examples; - -import java.io.IOException; -import java.io.UnsupportedEncodingException; -import java.net.InetSocketAddress; -import java.util.logging.Level; - -import org.eclipse.californium.scandium.DTLSConnector; -import org.eclipse.californium.scandium.ScandiumLogger; -import org.eclipse.californium.scandium.dtls.pskstore.InMemoryPskStore; -import org.eclipse.californium.scandium.util.ScProperties; - -import ch.ethz.inf.vs.elements.Connector; -import ch.ethz.inf.vs.elements.RawData; -import ch.ethz.inf.vs.elements.RawDataChannel; - -public class ExampleDTLSServer { - - static { - ScandiumLogger.initialize(); - ScandiumLogger.setLevel(Level.ALL); - } - - public static final int DEFAULT_PORT = ScProperties.std.getInt("DEFAULT_PORT"); - - private Connector dtlsConnector; - - public ExampleDTLSServer() { - InMemoryPskStore pskStore = new InMemoryPskStore(); - try { - // put in the PSK store the default identity/psk for tinydtls tests - pskStore.setPsk("Client_identity", "secretPSK".getBytes("US-ASCII")); - } catch (UnsupportedEncodingException e) { - throw new IllegalStateException("no US-ASCII codec in your JVM", e); - } - - dtlsConnector = new DTLSConnector(new InetSocketAddress(DEFAULT_PORT), pskStore); - - dtlsConnector.setRawDataReceiver(new RawDataChannelImpl(dtlsConnector)); - } - - public void start() { - try { - dtlsConnector.start(); - } catch (IOException e) { - throw new IllegalStateException("Unexpected error starting the DTLS UDP server", e); - } - } - - private class RawDataChannelImpl implements RawDataChannel { - - private Connector connector; - - public RawDataChannelImpl(Connector con) { - this.connector = con; - } - - // @Override - public void receiveData(final RawData raw) { - if (raw.getAddress() == null) - throw new NullPointerException(); - if (raw.getPort() == 0) - throw new NullPointerException(); - - System.out.println(new String(raw.getBytes())); - connector.send(new RawData("ACK".getBytes(), raw.getAddress(), raw.getPort())); - } - } - - public static void main(String[] args) { - - ExampleDTLSServer server = new ExampleDTLSServer(); - server.start(); - - try { - System.in.read(); - } catch (IOException e) { - e.printStackTrace(); - } - } -} diff --git a/leshan-core/src/main/java/org/eclipse/californium/scandium/util/ScProperties.java b/leshan-core/src/main/java/org/eclipse/californium/scandium/util/ScProperties.java deleted file mode 100644 index 902cfc86..00000000 --- a/leshan-core/src/main/java/org/eclipse/californium/scandium/util/ScProperties.java +++ /dev/null @@ -1,192 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2014 Institute for Pervasive Computing, ETH Zurich and others. - * - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * and Eclipse Distribution License v1.0 which accompany this distribution. - * - * The Eclipse Public License is available at - * http://www.eclipse.org/legal/epl-v10.html - * and the Eclipse Distribution License is available at - * http://www.eclipse.org/org/documents/edl-v10.html. - * - * Contributors: - * Matthias Kovatsch - creator and main architect - * Stefan Jucker - DTLS implementation - ******************************************************************************/ -package org.eclipse.californium.scandium.util; - -import java.io.FileInputStream; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.util.logging.Logger; - -import org.eclipse.californium.scandium.dtls.cipher.CipherSuite; - - -/** - * This class implements Californium's property registry. - * - * It is used to manage CoAP- and Californium-specific constants in a central - * place. The properties are initialized in the init() section and can be - * overridden by a user-defined .properties file. If the file does not exist - * upon initialization, it will be created so that a valid configuration always - * exists. - */ -public class ScProperties extends java.util.Properties { - - private static final Logger LOG = Logger.getLogger(ScProperties.class.getCanonicalName()); - - /** - * auto-generated to eliminate warning - */ - private static final long serialVersionUID = 8499865907306466190L; - - /** The header for Californium property files. */ - private static final String HEADER = "Scandium Properties file"; - - /** The name of the default properties file. */ - private static final String DEFAULT_FILENAME = "Scandium.properties"; - - // default properties used by the library - public static final ScProperties std = new ScProperties(DEFAULT_FILENAME); - - // Constructors //////////////////////////////////////////////////////////// - - public ScProperties(String fileName) { - init(); - initUserDefined(fileName); - } - - public Double getDbl(String key) { - String value = getProperty(key); - if (value != null) { - try { - return Double.parseDouble(value); - } catch (NumberFormatException e) { - LOG.severe(String.format("Invalid double property: %s=%s", key, value)); - } - } else { - LOG.severe(String.format("Undefined double property: %s", key)); - } - return 0.0; - } - - public int getInt(String key) { - String value = getProperty(key); - if (value != null) { - try { - return Integer.parseInt(value.trim()); - } catch (NumberFormatException e) { - LOG.severe(String.format("Invalid integer property: %s=%s", key, value)); - } - } else { - LOG.severe(String.format("Undefined integer property: %s", key)); - } - return 0; - } - - public String getStr(String key) { - String value = getProperty(key); - if (value == null) { - LOG.severe(String.format("Undefined string property: %s", key)); - } - return value; - } - - public boolean getBool(String key) { - String value = getProperty(key); - if (value != null) { - try { - return Boolean.parseBoolean(value); - } catch (NumberFormatException e) { - LOG.severe(String.format("Invalid boolean property: %s=%s", key, value)); - } - } else { - LOG.severe(String.format("Undefined boolean property: %s", key)); - } - return false; - } - - public void load(String fileName) throws IOException { - InputStream in = new FileInputStream(fileName); - load(in); - } - - public void set(String key, double value) { - setProperty(key, String.valueOf(value)); - } - - public void set(String key, int value) { - setProperty(key, String.valueOf(value)); - } - - public void set(String key, String value) { - setProperty(key, value); - } - - public void set(String key, boolean value) { - setProperty(key, String.valueOf(value)); - } - - public void store(String fileName) throws IOException { - OutputStream out = new FileOutputStream(fileName); - store(out, HEADER); - } - - private void init() { - - /* DTLS constants */ - set("DEFAULT_PORT", 5683); - - // the location of the key store (contains private key and corresponding - // certificate chain) - set("KEY_STORE_LOCATION", "certs/keyStore.jks"); - - // the location of the trust store (contains all trusted certificate - // authorities) - set("TRUST_STORE_LOCATION", "certs/trustStore.jks"); - - // the preferred cipher suite - // SSL_NULL_WITH_NULL_NULL - // TLS_PSK_WITH_AES_128_CCM_8 - // TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8 - set("PREFERRED_CIPHER_SUITE", CipherSuite.TLS_PSK_WITH_AES_128_CCM_8.toString()); - - // the identity hint when using the pre-shared key mode - set("PSK_IDENTITY", "PSK_Identity"); - - // whether the certificate message should only contain the peer's public - // key or the full X.509 certificate - set("USE_RAW_PUBLIC_KEY", true); - - // whether the server requires mutual authentication - set("CLIENT_AUTHENTICATION", false); - - // the initial timer value for retransmission; rfc6347, section: 4.2.4.1 - set("RETRANSMISSION_TIMEOUT", 1000); // [milliseconds] - - // maximal number of retransmissions before the attempt to transmit a message is canceled - set("MAX_RETRANSMIT", 4); - - // the maximum fragment size before DTLS fragmentation must be applied - set("MAX_FRAGMENT_LENGTH", 4096); // [bytes] - } - - private void initUserDefined(String fileName) { - try { - load(fileName); - } catch (IOException e) { - // file does not exist: - // write default properties - try { - store(fileName); - } catch (IOException e1) { - LOG.warning(String.format("Failed to create configuration file: %s", e1.getMessage())); - } - } - } - -}