001: /**
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */package org.apache.geronimo.crypto.jce.provider;
017:
018: import java.io.ByteArrayOutputStream;
019: import java.io.IOException;
020: import java.math.BigInteger;
021: import java.security.InvalidKeyException;
022: import java.security.NoSuchAlgorithmException;
023: import java.security.NoSuchProviderException;
024: import java.security.Principal;
025: import java.security.Provider;
026: import java.security.PublicKey;
027: import java.security.Security;
028: import java.security.Signature;
029: import java.security.SignatureException;
030: import java.security.cert.CRLException;
031: import java.security.cert.Certificate;
032: import java.security.cert.X509CRL;
033: import java.security.cert.X509CRLEntry;
034: import java.security.cert.X509Certificate;
035: import java.util.Date;
036: import java.util.Enumeration;
037: import java.util.HashSet;
038: import java.util.Set;
039:
040: import javax.security.auth.x500.X500Principal;
041:
042: import org.apache.geronimo.crypto.asn1.ASN1OutputStream;
043: import org.apache.geronimo.crypto.asn1.DERObjectIdentifier;
044: import org.apache.geronimo.crypto.asn1.DEROutputStream;
045: import org.apache.geronimo.crypto.asn1.x509.CertificateList;
046: import org.apache.geronimo.crypto.asn1.x509.TBSCertList;
047: import org.apache.geronimo.crypto.asn1.x509.X509Extension;
048: import org.apache.geronimo.crypto.asn1.x509.X509Extensions;
049: import org.apache.geronimo.crypto.jce.X509Principal;
050:
051: /**
052: * The following extensions are listed in RFC 2459 as relevant to CRLs
053: *
054: * Authority Key Identifier
055: * Issuer Alternative Name
056: * CRL Number
057: * Delta CRL Indicator (critical)
058: * Issuing Distribution Point (critical)
059: */
060: public class X509CRLObject extends X509CRL {
061: private CertificateList c;
062:
063: public X509CRLObject(CertificateList c) {
064: this .c = c;
065: }
066:
067: /**
068: * Will return true if any extensions are present and marked
069: * as critical as we currently dont handle any extensions!
070: */
071: public boolean hasUnsupportedCriticalExtension() {
072: Set extns = getCriticalExtensionOIDs();
073: if (extns != null && !extns.isEmpty()) {
074: return true;
075: }
076:
077: return false;
078: }
079:
080: private Set getExtensionOIDs(boolean critical) {
081: if (this .getVersion() == 2) {
082: HashSet set = new HashSet();
083: X509Extensions extensions = c.getTBSCertList()
084: .getExtensions();
085: Enumeration e = extensions.oids();
086:
087: while (e.hasMoreElements()) {
088: DERObjectIdentifier oid = (DERObjectIdentifier) e
089: .nextElement();
090: X509Extension ext = extensions.getExtension(oid);
091:
092: if (critical == ext.isCritical()) {
093: set.add(oid.getId());
094: }
095: }
096:
097: return set;
098: }
099:
100: return null;
101: }
102:
103: public Set getCriticalExtensionOIDs() {
104: return getExtensionOIDs(true);
105: }
106:
107: public Set getNonCriticalExtensionOIDs() {
108: return getExtensionOIDs(false);
109: }
110:
111: public byte[] getExtensionValue(String oid) {
112: X509Extensions exts = c.getTBSCertList().getExtensions();
113:
114: if (exts != null) {
115: X509Extension ext = exts
116: .getExtension(new DERObjectIdentifier(oid));
117:
118: if (ext != null) {
119: ByteArrayOutputStream bOut = new ByteArrayOutputStream();
120: DEROutputStream dOut = new DEROutputStream(bOut);
121:
122: try {
123: dOut.writeObject(ext.getValue());
124:
125: return bOut.toByteArray();
126: } catch (Exception e) {
127: throw new RuntimeException("error encoding "
128: + e.getMessage(), e);
129: }
130: }
131: }
132:
133: return null;
134: }
135:
136: public byte[] getEncoded() throws CRLException {
137: ByteArrayOutputStream bOut = new ByteArrayOutputStream();
138: DEROutputStream dOut = new DEROutputStream(bOut);
139:
140: try {
141: dOut.writeObject(c);
142:
143: return bOut.toByteArray();
144: } catch (IOException e) {
145: throw (CRLException) new CRLException(e.getMessage())
146: .initCause(e);
147: }
148: }
149:
150: public void verify(PublicKey key) throws CRLException,
151: NoSuchAlgorithmException, InvalidKeyException,
152: NoSuchProviderException, SignatureException {
153: verify(key, "BC");
154: }
155:
156: public void verify(PublicKey key, String sigProvider)
157: throws CRLException, NoSuchAlgorithmException,
158: InvalidKeyException, NoSuchProviderException,
159: SignatureException {
160: if (!c.getSignatureAlgorithm().equals(
161: c.getTBSCertList().getSignature())) {
162: throw new CRLException(
163: "Signature algorithm on CertifcateList does not match TBSCertList.");
164: }
165:
166: Signature sig = Signature.getInstance(getSigAlgName(),
167: sigProvider);
168:
169: sig.initVerify(key);
170: sig.update(this .getTBSCertList());
171: if (!sig.verify(this .getSignature())) {
172: throw new SignatureException(
173: "CRL does not verify with supplied public key.");
174: }
175: }
176:
177: public int getVersion() {
178: return c.getVersion();
179: }
180:
181: public Principal getIssuerDN() {
182: return new X509Principal(c.getIssuer());
183: }
184:
185: public X500Principal getIssuerX500Principal() {
186: try {
187: ByteArrayOutputStream bOut = new ByteArrayOutputStream();
188: ASN1OutputStream aOut = new ASN1OutputStream(bOut);
189:
190: aOut.writeObject(c.getIssuer());
191:
192: return new X500Principal(bOut.toByteArray());
193: } catch (IOException e) {
194: throw new IllegalStateException("can't encode issuer DN", e);
195: }
196: }
197:
198: public Date getThisUpdate() {
199: return c.getThisUpdate().getDate();
200: }
201:
202: public Date getNextUpdate() {
203: if (c.getNextUpdate() != null) {
204: return c.getNextUpdate().getDate();
205: }
206:
207: return null;
208: }
209:
210: public X509CRLEntry getRevokedCertificate(BigInteger serialNumber) {
211: TBSCertList.CRLEntry[] certs = c.getRevokedCertificates();
212:
213: if (certs != null) {
214: for (int i = 0; i < certs.length; i++) {
215: if (certs[i].getUserCertificate().getValue().equals(
216: serialNumber)) {
217: return new X509CRLEntryObject(certs[i]);
218: }
219: }
220: }
221:
222: return null;
223: }
224:
225: public Set getRevokedCertificates() {
226: TBSCertList.CRLEntry[] certs = c.getRevokedCertificates();
227:
228: if (certs != null) {
229: HashSet set = new HashSet();
230: for (int i = 0; i < certs.length; i++) {
231: set.add(new X509CRLEntryObject(certs[i]));
232:
233: }
234:
235: return set;
236: }
237:
238: return null;
239: }
240:
241: public byte[] getTBSCertList() throws CRLException {
242: ByteArrayOutputStream bOut = new ByteArrayOutputStream();
243: DEROutputStream dOut = new DEROutputStream(bOut);
244:
245: try {
246: dOut.writeObject(c.getTBSCertList());
247:
248: return bOut.toByteArray();
249: } catch (IOException e) {
250: throw (CRLException) new CRLException(e.getMessage())
251: .initCause(e);
252: }
253: }
254:
255: public byte[] getSignature() {
256: return c.getSignature().getBytes();
257: }
258:
259: public String getSigAlgName() {
260: Provider[] provs = Security.getProviders();
261:
262: //
263: // search every provider looking for a real algorithm
264: //
265: for (int i = 0; i != provs.length; i++) {
266: String algName = provs[i]
267: .getProperty("Alg.Alias.Signature."
268: + this .getSigAlgOID());
269: if (algName != null) {
270: return algName;
271: }
272: }
273:
274: return this .getSigAlgOID();
275: }
276:
277: public String getSigAlgOID() {
278: return c.getSignatureAlgorithm().getObjectId().getId();
279: }
280:
281: public byte[] getSigAlgParams() {
282: ByteArrayOutputStream bOut = new ByteArrayOutputStream();
283:
284: if (c.getSignatureAlgorithm().getParameters() != null) {
285: try {
286: DEROutputStream dOut = new DEROutputStream(bOut);
287:
288: dOut.writeObject(c.getSignatureAlgorithm()
289: .getParameters());
290: } catch (Exception e) {
291: throw new RuntimeException(
292: "exception getting sig parameters "
293: + e.getMessage(), e);
294: }
295:
296: return bOut.toByteArray();
297: }
298:
299: return null;
300: }
301:
302: /**
303: * Returns a string representation of this CRL.
304: *
305: * @return a string representation of this CRL.
306: */
307: public String toString() {
308: return "X.509 CRL";
309: }
310:
311: /**
312: * Checks whether the given certificate is on this CRL.
313: *
314: * @param cert the certificate to check for.
315: * @return true if the given certificate is on this CRL,
316: * false otherwise.
317: */
318: public boolean isRevoked(Certificate cert) {
319: if (!cert.getType().equals("X.509")) {
320: throw new RuntimeException(
321: "X.509 CRL used with non X.509 Cert");
322: }
323:
324: TBSCertList.CRLEntry[] certs = c.getRevokedCertificates();
325:
326: if (certs != null) {
327: BigInteger serial = ((X509Certificate) cert)
328: .getSerialNumber();
329:
330: for (int i = 0; i < certs.length; i++) {
331: if (certs[i].getUserCertificate().getValue().equals(
332: serial)) {
333: return true;
334: }
335: }
336: }
337:
338: return false;
339: }
340: }
|