001: package org.bouncycastle.ocsp;
002:
003: import java.io.ByteArrayOutputStream;
004: import java.io.IOException;
005: import java.security.InvalidKeyException;
006: import java.security.NoSuchAlgorithmException;
007: import java.security.NoSuchProviderException;
008: import java.security.PrivateKey;
009: import java.security.SecureRandom;
010: import java.security.cert.CertificateEncodingException;
011: import java.security.cert.X509Certificate;
012: import java.util.ArrayList;
013: import java.util.Iterator;
014: import java.util.List;
015:
016: import javax.security.auth.x500.X500Principal;
017:
018: import org.bouncycastle.asn1.ASN1EncodableVector;
019: import org.bouncycastle.asn1.ASN1InputStream;
020: import org.bouncycastle.asn1.ASN1OutputStream;
021: import org.bouncycastle.asn1.ASN1Sequence;
022: import org.bouncycastle.asn1.DERBitString;
023: import org.bouncycastle.asn1.DERNull;
024: import org.bouncycastle.asn1.DERObject;
025: import org.bouncycastle.asn1.DERObjectIdentifier;
026: import org.bouncycastle.asn1.DERSequence;
027: import org.bouncycastle.asn1.ocsp.OCSPRequest;
028: import org.bouncycastle.asn1.ocsp.Request;
029: import org.bouncycastle.asn1.ocsp.Signature;
030: import org.bouncycastle.asn1.ocsp.TBSRequest;
031: import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
032: import org.bouncycastle.asn1.x509.GeneralName;
033: import org.bouncycastle.asn1.x509.X509CertificateStructure;
034: import org.bouncycastle.asn1.x509.X509Extensions;
035: import org.bouncycastle.jce.X509Principal;
036:
037: public class OCSPReqGenerator {
038: private List list = new ArrayList();
039: private GeneralName requestorName = null;
040: private X509Extensions requestExtensions = null;
041:
042: private class RequestObject {
043: CertificateID certId;
044: X509Extensions extensions;
045:
046: public RequestObject(CertificateID certId,
047: X509Extensions extensions) {
048: this .certId = certId;
049: this .extensions = extensions;
050: }
051:
052: public Request toRequest() throws Exception {
053: return new Request(certId.toASN1Object(), extensions);
054: }
055: }
056:
057: private DERObject makeObj(byte[] encoding) throws IOException {
058: if (encoding == null) {
059: return null;
060: }
061:
062: ASN1InputStream aIn = new ASN1InputStream(encoding);
063:
064: return aIn.readObject();
065: }
066:
067: /**
068: * Add a request for the given CertificateID.
069: *
070: * @param certId certificate ID of interest
071: */
072: public void addRequest(CertificateID certId) {
073: list.add(new RequestObject(certId, null));
074: }
075:
076: /**
077: * Add a request with extensions
078: *
079: * @param certId certificate ID of interest
080: * @param singleRequestExtensions the extensions to attach to the request
081: */
082: public void addRequest(CertificateID certId,
083: X509Extensions singleRequestExtensions) {
084: list.add(new RequestObject(certId, singleRequestExtensions));
085: }
086:
087: /**
088: * Set the requestor name to the passed in X500Principal
089: *
090: * @param requestorName a X500Principal representing the requestor name.
091: */
092: public void setRequestorName(X500Principal requestorName) {
093: try {
094: this .requestorName = new GeneralName(
095: GeneralName.directoryName, new X509Principal(
096: requestorName.getEncoded()));
097: } catch (IOException e) {
098: throw new IllegalArgumentException(
099: "cannot encode principal: " + e);
100: }
101: }
102:
103: public void setRequestorName(GeneralName requestorName) {
104: this .requestorName = requestorName;
105: }
106:
107: public void setRequestExtensions(X509Extensions requestExtensions) {
108: this .requestExtensions = requestExtensions;
109: }
110:
111: private OCSPReq generateRequest(
112: DERObjectIdentifier signingAlgorithm, PrivateKey key,
113: X509Certificate[] chain, String provider,
114: SecureRandom random) throws OCSPException,
115: NoSuchProviderException {
116: Iterator it = list.iterator();
117:
118: ASN1EncodableVector requests = new ASN1EncodableVector();
119:
120: while (it.hasNext()) {
121: try {
122: requests.add(((RequestObject) it.next()).toRequest());
123: } catch (Exception e) {
124: throw new OCSPException("exception creating Request", e);
125: }
126: }
127:
128: TBSRequest tbsReq = new TBSRequest(requestorName,
129: new DERSequence(requests), requestExtensions);
130:
131: java.security.Signature sig = null;
132: Signature signature = null;
133:
134: if (signingAlgorithm != null) {
135: if (requestorName == null) {
136: throw new OCSPException(
137: "requestorName must be specified if request is signed.");
138: }
139:
140: try {
141: sig = java.security.Signature.getInstance(
142: signingAlgorithm.getId(), provider);
143: if (random != null) {
144: sig.initSign(key, random);
145: } else {
146: sig.initSign(key);
147: }
148:
149: } catch (NoSuchAlgorithmException e) {
150: throw new OCSPException(
151: "exception creating signature: " + e, e);
152: } catch (InvalidKeyException e) {
153: throw new OCSPException(
154: "exception creating signature: " + e, e);
155: }
156:
157: DERBitString bitSig = null;
158:
159: try {
160: ByteArrayOutputStream bOut = new ByteArrayOutputStream();
161: ASN1OutputStream aOut = new ASN1OutputStream(bOut);
162:
163: aOut.writeObject(tbsReq);
164:
165: sig.update(bOut.toByteArray());
166:
167: bitSig = new DERBitString(sig.sign());
168: } catch (Exception e) {
169: throw new OCSPException(
170: "exception processing TBSRequest: " + e, e);
171: }
172:
173: AlgorithmIdentifier sigAlgId = new AlgorithmIdentifier(
174: signingAlgorithm, new DERNull());
175:
176: if (chain != null && chain.length > 0) {
177: ASN1EncodableVector v = new ASN1EncodableVector();
178: try {
179: for (int i = 0; i != chain.length; i++) {
180: v.add(new X509CertificateStructure(
181: (ASN1Sequence) makeObj(chain[i]
182: .getEncoded())));
183: }
184: } catch (IOException e) {
185: throw new OCSPException("error processing certs", e);
186: } catch (CertificateEncodingException e) {
187: throw new OCSPException("error encoding certs", e);
188: }
189:
190: signature = new Signature(sigAlgId, bitSig,
191: new DERSequence(v));
192: } else {
193: signature = new Signature(sigAlgId, bitSig);
194: }
195: }
196:
197: return new OCSPReq(new OCSPRequest(tbsReq, signature));
198: }
199:
200: /**
201: * Generate an unsigned request
202: *
203: * @return the OCSPReq
204: * @throws OCSPException
205: */
206: public OCSPReq generate() throws OCSPException {
207: try {
208: return generateRequest(null, null, null, null, null);
209: } catch (NoSuchProviderException e) {
210: //
211: // this shouldn't happen but...
212: //
213: throw new OCSPException("no provider! - " + e, e);
214: }
215: }
216:
217: public OCSPReq generate(String signingAlgorithm, PrivateKey key,
218: X509Certificate[] chain, String provider)
219: throws OCSPException, NoSuchProviderException,
220: IllegalArgumentException {
221: return generate(signingAlgorithm, key, chain, provider, null);
222: }
223:
224: public OCSPReq generate(String signingAlgorithm, PrivateKey key,
225: X509Certificate[] chain, String provider,
226: SecureRandom random) throws OCSPException,
227: NoSuchProviderException, IllegalArgumentException {
228: if (signingAlgorithm == null) {
229: throw new IllegalArgumentException(
230: "no signing algorithm specified");
231: }
232:
233: try {
234: DERObjectIdentifier oid = OCSPUtil
235: .getAlgorithmOID(signingAlgorithm);
236:
237: return generateRequest(oid, key, chain, provider, random);
238: } catch (IllegalArgumentException e) {
239: throw new IllegalArgumentException(
240: "unknown signing algorithm specified: "
241: + signingAlgorithm);
242: }
243: }
244:
245: /**
246: * Return an iterator of the signature names supported by the generator.
247: *
248: * @return an iterator containing recognised names.
249: */
250: public Iterator getSignatureAlgNames() {
251: return OCSPUtil.getAlgNames();
252: }
253: }
|