/*
* Copyright (c) 2015 Huawei, Inc and others. 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 org.opendaylight.usc.crypto.dtls;
import java.io.File;
import java.io.IOException;
import java.io.PrintStream;
import java.util.Vector;
import org.bouncycastle.asn1.x500.X500Name;
import org.bouncycastle.asn1.x509.Certificate;
import org.bouncycastle.crypto.tls.AlertDescription;
import org.bouncycastle.crypto.tls.AlertLevel;
import org.bouncycastle.crypto.tls.CertificateRequest;
import org.bouncycastle.crypto.tls.CipherSuite;
import org.bouncycastle.crypto.tls.ClientCertificateType;
import org.bouncycastle.crypto.tls.DefaultTlsServer;
import org.bouncycastle.crypto.tls.HashAlgorithm;
import org.bouncycastle.crypto.tls.ProtocolVersion;
import org.bouncycastle.crypto.tls.SignatureAlgorithm;
import org.bouncycastle.crypto.tls.SignatureAndHashAlgorithm;
import org.bouncycastle.crypto.tls.TlsEncryptionCredentials;
import org.bouncycastle.crypto.tls.TlsSignerCredentials;
import org.bouncycastle.crypto.tls.TlsUtils;
import org.bouncycastle.util.Arrays;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class DtlsServer extends DefaultTlsServer {
private static final Logger log = LoggerFactory.getLogger(DtlsServer.class);
private final File root;
private final File cert;
private final File key;
public DtlsServer(File root, File cert, File key) {
super();
this.root = root;
this.cert = cert;
this.key = key;
}
public void notifyAlertRaised(short alertLevel, short alertDescription, String message, Throwable cause) {
PrintStream out = (alertLevel == AlertLevel.fatal) ? System.err : System.out;
out.println("DTLS server raised alert: " + AlertLevel.getText(alertLevel) + ", "
+ AlertDescription.getText(alertDescription));
if (message != null) {
out.println(message);
}
if (cause != null) {
cause.printStackTrace(out);
}
}
public void notifyAlertReceived(short alertLevel, short alertDescription) {
PrintStream out = (alertLevel == AlertLevel.fatal) ? System.err : System.out;
out.println("DTLS server received alert: " + AlertLevel.getText(alertLevel) + ", "
+ AlertDescription.getText(alertDescription));
out.close();
}
protected int[] getCipherSuites() {
return Arrays.concatenate(super.getCipherSuites(), new int[] {
CipherSuite.DRAFT_TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256, });
}
public CertificateRequest getCertificateRequest() throws IOException {
Vector<SignatureAndHashAlgorithm> serverSigAlgs = null;
if (TlsUtils.isSignatureAlgorithmsExtensionAllowed(serverVersion)) {
short[] hashAlgorithms = new short[] { HashAlgorithm.sha512, HashAlgorithm.sha384, HashAlgorithm.sha256,
HashAlgorithm.sha224, HashAlgorithm.sha1 };
short[] signatureAlgorithms = new short[] { SignatureAlgorithm.rsa };
serverSigAlgs = new Vector<SignatureAndHashAlgorithm>();
for (int i = 0; i < hashAlgorithms.length; ++i) {
for (int j = 0; j < signatureAlgorithms.length; ++j) {
serverSigAlgs.addElement(new SignatureAndHashAlgorithm(hashAlgorithms[i], signatureAlgorithms[j]));
}
}
}
Vector<X500Name> certificateAuthorities = new Vector<X500Name>();
certificateAuthorities.add(DtlsUtils.loadCertificateResource(root.getAbsolutePath()).getSubject());
return new CertificateRequest(new short[] { ClientCertificateType.rsa_sign }, serverSigAlgs,
certificateAuthorities);
}
public void notifyClientCertificate(org.bouncycastle.crypto.tls.Certificate clientCertificate) throws IOException {
Certificate[] chain = clientCertificate.getCertificateList();
log.trace("Received client certificate chain of length " + chain.length);
for (int i = 0; i != chain.length; i++) {
Certificate entry = chain[i];
// TODO Create fingerprint based on certificate signature algorithm digest
log.trace(" fingerprint:SHA-256 " + DtlsUtils.fingerprint(entry) + " (" + entry.getSubject() + ")");
}
}
protected ProtocolVersion getMaximumVersion() {
return ProtocolVersion.DTLSv12;
}
protected ProtocolVersion getMinimumVersion() {
return ProtocolVersion.DTLSv10;
}
protected TlsEncryptionCredentials getRSAEncryptionCredentials() throws IOException {
return DtlsUtils.loadEncryptionCredentials(context,
new String[] { cert.getAbsolutePath(), root.getAbsolutePath() }, key.getAbsolutePath());
}
protected TlsSignerCredentials getRSASignerCredentials() throws IOException {
/*
* TODO Note that this code fails to provide default value for the client supported algorithms if it wasn't
* sent.
*/
SignatureAndHashAlgorithm signatureAndHashAlgorithm = null;
Vector<?> sigAlgs = supportedSignatureAlgorithms;
if (sigAlgs != null) {
for (int i = 0; i < sigAlgs.size(); ++i) {
SignatureAndHashAlgorithm sigAlg = (SignatureAndHashAlgorithm) sigAlgs.elementAt(i);
if (sigAlg.getSignature() == SignatureAlgorithm.rsa) {
signatureAndHashAlgorithm = sigAlg;
break;
}
}
if (signatureAndHashAlgorithm == null) {
return null;
}
}
return DtlsUtils.loadSignerCredentials(context,
new String[] { cert.getAbsolutePath(), root.getAbsolutePath() }, key.getAbsolutePath(),
signatureAndHashAlgorithm);
}
}