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

Add support for server certificate authenticity verification #24

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
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

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
package net.jradius.tls;

import org.bouncycastle.asn1.x509.X509CertificateStructure;
import org.bouncycastle.asn1.x509.Certificate;

/**
* A certificate verifyer, that will always return true.
*
*
* <pre>
* DO NOT USE THIS FILE UNLESS YOU KNOW EXACTLY WHAT YOU ARE DOING.
* </pre>
Expand All @@ -13,10 +13,10 @@ public class AlwaysValidVerifyer implements CertificateVerifyer
{
/**
* Return true.
*
*
* @see org.bouncycastle.crypto.tls.CertificateVerifyer#isValid(org.bouncycastle.asn1.x509.X509CertificateStructure[])
*/
public boolean isValid(X509CertificateStructure[] certs)
public boolean isValid(Certificate[] certs)
{
return true;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,32 +4,35 @@
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.util.Vector;

import org.bouncycastle.asn1.ASN1InputStream;
import org.bouncycastle.asn1.ASN1Primitive;
import org.bouncycastle.asn1.x509.X509CertificateStructure;
import org.bouncycastle.asn1.x509.Certificate;

/**
* A representation for a certificate chain as used by a tls server.
*/
public class Certificate
public class CertificateChain
{
/**
* The certificates.
*/
protected X509CertificateStructure[] certs;
protected Certificate[] certs;

/**
* Parse the ServerCertificate message.
*
*
* @param is The stream where to parse from.
* @return A Certificate object with the certs, the server has sended.
* @throws IOException If something goes wrong during parsing.
*/
public static Certificate parse(InputStream is) throws IOException
public static CertificateChain parse(InputStream is) throws IOException
{
X509CertificateStructure[] certs;
Certificate[] certs;
int left = TlsUtils.readUint24(is);
Vector tmp = new Vector();
while (left > 0)
Expand All @@ -41,24 +44,24 @@ public static Certificate parse(InputStream is) throws IOException
ByteArrayInputStream bis = new ByteArrayInputStream(buf);
ASN1InputStream ais = new ASN1InputStream(bis);
ASN1Primitive o = ais.readObject();
tmp.addElement(X509CertificateStructure.getInstance(o));
tmp.addElement(Certificate.getInstance(o));
if (bis.available() > 0)
{
throw new IllegalArgumentException(
"Sorry, there is garbage data left after the certificate");
}
}
certs = new X509CertificateStructure[tmp.size()];
certs = new Certificate[tmp.size()];
for (int i = 0; i < tmp.size(); i++)
{
certs[i] = (X509CertificateStructure)tmp.elementAt(i);
certs[i] = (Certificate)tmp.elementAt(i);
}
return new Certificate(certs);
return new CertificateChain(certs);
}

/**
* Encodes version of the ClientCertificate message
*
*
* @param os stream to write the message to
* @throws IOException If something goes wrong
*/
Expand All @@ -85,21 +88,34 @@ protected void encode(OutputStream os) throws IOException

/**
* Private constructor from a cert array.
*
*
* @param certs The certs the chain should contain.
*/
public Certificate(X509CertificateStructure[] certs)
public CertificateChain(Certificate[] certs)
{
this.certs = certs;
}

/**
* @return An array which contains the certs, this chain contains.
*/
public X509CertificateStructure[] getCerts()
public Certificate[] getCerts()
{
X509CertificateStructure[] result = new X509CertificateStructure[certs.length];
Certificate[] result = new Certificate[certs.length];
System.arraycopy(certs, 0, result, 0, certs.length);
return result;
}

public X509Certificate[] toX509() throws IOException, CertificateException {
X509Certificate[] x509 = new X509Certificate[certs.length];
for (int i = 0; i < certs.length; i++) {
Certificate cert = certs[i];
InputStream in = new ByteArrayInputStream(cert.getEncoded());
CertificateFactory certFactory = CertificateFactory.getInstance("X.509");
x509[i] = (X509Certificate)certFactory.generateCertificate(in);
in.close();
}

return x509;
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package net.jradius.tls;

import org.bouncycastle.asn1.x509.X509CertificateStructure;
import org.bouncycastle.asn1.x509.Certificate;

/**
* This should be implemented by any class which can find out, if a given certificate
Expand All @@ -12,5 +12,5 @@ public interface CertificateVerifyer
* @param certs The certs, which are part of the chain.
* @return True, if the chain is accepted, false otherwise.
*/
public boolean isValid(X509CertificateStructure[] certs);
public boolean isValid(Certificate[] certs);
}
34 changes: 18 additions & 16 deletions extended/src/main/java/net/jradius/tls/DefaultTlsClient.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
import java.util.Hashtable;
import java.util.List;

import org.bouncycastle.asn1.x509.X509CertificateStructure;
import org.bouncycastle.asn1.x509.Certificate;
import org.bouncycastle.crypto.BlockCipher;
import org.bouncycastle.crypto.CryptoException;
import org.bouncycastle.crypto.digests.SHA1Digest;
Expand All @@ -15,6 +15,8 @@
import org.bouncycastle.crypto.params.DSAPrivateKeyParameters;
import org.bouncycastle.crypto.params.RSAKeyParameters;

import net.jradius.tls.TlsKeyExchange.Algorithm;

public class DefaultTlsClient implements TlsClient
{
// TODO Add runtime support for this check?
Expand Down Expand Up @@ -63,12 +65,12 @@ public class DefaultTlsClient implements TlsClient
private static final int TLS_SRP_SHA_RSA_WITH_AES_256_CBC_SHA = 0xC021;
private static final int TLS_SRP_SHA_DSS_WITH_AES_256_CBC_SHA = 0xC022;

private CertificateVerifyer verifyer;
private final CertificateVerifyer verifyer;

private TlsProtocolHandler handler;

// (Optional) details for client-side authentication
private Certificate clientCert = new Certificate(new X509CertificateStructure[0]);
private CertificateChain clientCert = new CertificateChain(new Certificate[0]);
private AsymmetricKeyParameter clientPrivateKey = null;
private TlsSigner clientSigner = null;

Expand All @@ -79,7 +81,7 @@ public DefaultTlsClient(CertificateVerifyer verifyer)
this.verifyer = verifyer;
}

public void enableClientAuthentication(Certificate clientCertificate,
public void enableClientAuthentication(CertificateChain clientCertificate,
AsymmetricKeyParameter clientPrivateKey)
{
if (clientCertificate == null)
Expand Down Expand Up @@ -169,7 +171,7 @@ public Hashtable generateClientExtensions()

public void notifySessionID(byte[] sessionID)
{
// Currently ignored
// Currently ignored
}

public void notifySelectedCipherSuite(int selectedCipherSuite)
Expand All @@ -195,37 +197,37 @@ public TlsKeyExchange createKeyExchange() throws IOException
case TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA:
case TLS_DH_DSS_WITH_AES_128_CBC_SHA:
case TLS_DH_DSS_WITH_AES_256_CBC_SHA:
return createDHKeyExchange(TlsKeyExchange.KE_DH_DSS);
return createDHKeyExchange(TlsKeyExchange.Algorithm.KE_DH_DSS);

case TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA:
case TLS_DH_RSA_WITH_AES_128_CBC_SHA:
case TLS_DH_RSA_WITH_AES_256_CBC_SHA:
return createDHKeyExchange(TlsKeyExchange.KE_DH_RSA);
return createDHKeyExchange(TlsKeyExchange.Algorithm.KE_DH_RSA);

case TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA:
case TLS_DHE_DSS_WITH_AES_128_CBC_SHA:
case TLS_DHE_DSS_WITH_AES_256_CBC_SHA:
return createDHKeyExchange(TlsKeyExchange.KE_DHE_DSS);
return createDHKeyExchange(TlsKeyExchange.Algorithm.KE_DHE_DSS);

case TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA:
case TLS_DHE_RSA_WITH_AES_128_CBC_SHA:
case TLS_DHE_RSA_WITH_AES_256_CBC_SHA:
return createDHKeyExchange(TlsKeyExchange.KE_DHE_RSA);
return createDHKeyExchange(TlsKeyExchange.Algorithm.KE_DHE_RSA);

case TLS_SRP_SHA_WITH_3DES_EDE_CBC_SHA:
case TLS_SRP_SHA_WITH_AES_128_CBC_SHA:
case TLS_SRP_SHA_WITH_AES_256_CBC_SHA:
return createSRPExchange(TlsKeyExchange.KE_SRP);
return createSRPExchange(TlsKeyExchange.Algorithm.KE_SRP);

case TLS_SRP_SHA_RSA_WITH_3DES_EDE_CBC_SHA:
case TLS_SRP_SHA_RSA_WITH_AES_128_CBC_SHA:
case TLS_SRP_SHA_RSA_WITH_AES_256_CBC_SHA:
return createSRPExchange(TlsKeyExchange.KE_SRP_RSA);
return createSRPExchange(TlsKeyExchange.Algorithm.KE_SRP_RSA);

case TLS_SRP_SHA_DSS_WITH_3DES_EDE_CBC_SHA:
case TLS_SRP_SHA_DSS_WITH_AES_128_CBC_SHA:
case TLS_SRP_SHA_DSS_WITH_AES_256_CBC_SHA:
return createSRPExchange(TlsKeyExchange.KE_SRP_DSS);
return createSRPExchange(TlsKeyExchange.Algorithm.KE_SRP_DSS);

default:
/*
Expand All @@ -242,7 +244,7 @@ public TlsKeyExchange createKeyExchange() throws IOException

public void processServerCertificateRequest(byte[] certificateTypes, List certificateAuthorities)
{
// TODO There shouldn't be a certificate request for SRP
// TODO There shouldn't be a certificate request for SRP

// TODO Use provided info to choose a certificate in getCertificate()
}
Expand All @@ -265,7 +267,7 @@ public byte[] generateCertificateSignature(byte[] md5andsha1) throws IOException
}
}

public Certificate getCertificate()
public CertificateChain getCertificate()
{
return clientCert;
}
Expand Down Expand Up @@ -317,7 +319,7 @@ public TlsCipher createCipher(SecurityParameters securityParameters) throws IOEx
}
}

private TlsKeyExchange createDHKeyExchange(short keyExchange)
private TlsKeyExchange createDHKeyExchange(Algorithm keyExchange)
{
return new TlsDHKeyExchange(handler, verifyer, keyExchange);
}
Expand All @@ -327,7 +329,7 @@ private TlsKeyExchange createRSAKeyExchange()
return new TlsRSAKeyExchange(handler, verifyer);
}

private TlsKeyExchange createSRPExchange(short keyExchange)
private TlsKeyExchange createSRPExchange(Algorithm keyExchange)
{
return new TlsSRPKeyExchange(handler, verifyer, keyExchange);
}
Expand Down
2 changes: 1 addition & 1 deletion extended/src/main/java/net/jradius/tls/TlsClient.java
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ interface TlsClient

byte[] generateCertificateSignature(byte[] md5andsha1) throws IOException;

Certificate getCertificate();
CertificateChain getCertificate();

TlsCipher createCipher(SecurityParameters securityParameters) throws IOException;
}
Loading