summaryrefslogtreecommitdiff
path: root/src/org/noreply/fancydress/type3/mmtp/MMTPTrustManager.java
blob: 32beb9ae8ca28aafed054e9d7fd2cf3649accebf (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
/* $Id$ */
package org.noreply.fancydress.type3.mmtp;

import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import javax.net.ssl.X509TrustManager;
import java.security.AlgorithmParameters;
import java.security.NoSuchAlgorithmException;
import java.security.InvalidKeyException;
import java.security.NoSuchProviderException;
import java.security.SignatureException;
import java.security.cert.CertificateNotYetValidException;
import java.security.cert.CertificateExpiredException;
import java.math.BigInteger;
import org.bouncycastle.util.encoders.Base64;
import org.noreply.fancydress.misc.*;
import org.noreply.fancydress.crypto.*;

public class MMTPTrustManager implements X509TrustManager {
	/**
	 * Hash of the expected identity key.
	 */
	private byte[] identity;

	/**
	 * Create a new MMTPTrustManager instance.
	 *
	 * @param keyid fingerprint (== keyid, == hash of the key) of the identity key.
	 */
	public MMTPTrustManager(byte[] identity) {
		this.identity = identity;
	}

	/**
	 * Given the partial or complete certificate chain provided by the
	 * peer, build a certificate path to a trusted root and return if it
	 * can be validated and is trusted for client SSL authentication based
	 * on the authentication type.
	 *
	 * @param chain the peer certificate chain
	 * @param authType the authentication type based on the client certificate
	 * @throws IllegalArgumentException if null or zero-length chain is
	 *                                  passed in for the chain parameter
	 *                                  or if null or zero-length string is
	 *                                  passed in for the authType
	 *                                  parameter 
	 * @throws CertificateException  if the certificate chain is not
	 *                               trusted by this TrustManager.
	 */
	public void checkClientTrusted(X509Certificate[] chain, String authType)
		throws CertificateException
	{
		throw new Error("Not needed\n");
	}

	/**
	 * Given the partial or complete certificate chain provided by the
	 * peer, build a certificate path to a trusted root and return if it
	 * can be validated and is trusted for server SSL authentication based
	 * on the authentication type.
	 *
	 * @param chain the peer certificate chain
	 * @param authType the key exchange algorithm used
	 * @throws IllegalArgumentException if null or zero-length chain is
	 *                                  passed in for the chain parameter
	 *                                  or if null or zero-length string is
	 *                                  passed in for the authType
	 *                                  parameter 
	 * @throws CertificateException  if the certificate chain is not
	 *                               trusted by this TrustManager.
	 */
	public void checkServerTrusted(X509Certificate[] chain, String authType)
		throws CertificateException
	{
		/* Make sure we got two keys */
		if (chain.length != 2)
			throw new CertificateException("Did not get excatly 2 certificates in cert chain.");

		/* Check, if the certs are valid.  Certs are valid if
		 * ValidAfter already passed and ValidUntil is still in the
		 * future
		 */
		try {
			chain[0].checkValidity();
		} catch (CertificateExpiredException e) {
			throw new CertificateException("Cert 0 not valid.  Caused by CertificateExpiredException.");
		} catch (CertificateNotYetValidException e) {
			throw new CertificateException("Cert 0 not valid.  Caused by CertificateNotYetValidException.");
		}
		try {
			chain[1].checkValidity();
		} catch (CertificateExpiredException e) {
			throw new CertificateException("Cert 1 not valid.  Caused by CertificateExpiredException.");
		} catch (CertificateNotYetValidException e) {
			throw new CertificateException("Cert 1 not valid.  Caused by CertificateNotYetValidException.");
		}

		/* Verify, that the first cert is signed by the second cert */
		java.security.interfaces.RSAPublicKey identityCertKey = (java.security.interfaces.RSAPublicKey) chain[1].getPublicKey();
		try {
			chain[0].verify(identityCertKey);
		} catch (NoSuchAlgorithmException e) {
			throw new CertificateException("Could not verify chain.  Caused by NoSuchAlgorithmException,");
		} catch (InvalidKeyException e) {
			throw new CertificateException("Could not verify chain.  Caused by InvalidKeyException,");
		} catch (NoSuchProviderException e) {
			throw new CertificateException("Could not verify chain.  Caused by NoSuchProviderException,");
		} catch (SignatureException e) {
			throw new CertificateException("Could not verify chain.  Caused by SignatureException,");
		};

		/* Verify, that the second cert is the identity key */
		BigInteger modulus = identityCertKey.getModulus();
		BigInteger exp = identityCertKey.getPublicExponent();
		RSAPublicKey rsa = new RSAPublicKey(modulus,exp);
		byte[] fpr = rsa.getFingerprint();
		if (!Util.equal(identity, fpr))
			throw new CertificateException("Identity key's fingerprint does not match expected value.");
	}

	/**
	 * Return an array of certificate authority certificates which are
	 * trusted for authenticating peers.
	 *
	 * @return a non-null (possibly empty) array of acceptable CA issuer
	 *         certificates.
	 */
	public X509Certificate[] getAcceptedIssuers() {
		throw new Error("Not needed\n");
	}
}