blob: 56959071be28fb91f5ebbf8b13432aa50eacc414 [file] [log] [blame]
package org.bouncycastle.cert.ocsp;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import org.bouncycastle.asn1.ASN1EncodableVector;
import org.bouncycastle.asn1.ASN1Encoding;
import org.bouncycastle.asn1.ASN1GeneralizedTime;
import org.bouncycastle.asn1.DERBitString;
import org.bouncycastle.asn1.DERGeneralizedTime;
import org.bouncycastle.asn1.DERNull;
import org.bouncycastle.asn1.DERSequence;
import org.bouncycastle.asn1.ocsp.BasicOCSPResponse;
import org.bouncycastle.asn1.ocsp.CertStatus;
import org.bouncycastle.asn1.ocsp.ResponseData;
import org.bouncycastle.asn1.ocsp.RevokedInfo;
import org.bouncycastle.asn1.ocsp.SingleResponse;
import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
import org.bouncycastle.asn1.x509.CRLReason;
import org.bouncycastle.asn1.x509.Extensions;
import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo;
import org.bouncycastle.cert.X509CertificateHolder;
import org.bouncycastle.operator.ContentSigner;
import org.bouncycastle.operator.DigestCalculator;
/**
* Generator for basic OCSP response objects.
*/
public class BasicOCSPRespBuilder
{
private List list = new ArrayList();
private Extensions responseExtensions = null;
private RespID responderID;
private class ResponseObject
{
CertificateID certId;
CertStatus certStatus;
ASN1GeneralizedTime thisUpdate;
ASN1GeneralizedTime nextUpdate;
Extensions extensions;
public ResponseObject(
CertificateID certId,
CertificateStatus certStatus,
Date thisUpdate,
Date nextUpdate,
Extensions extensions)
{
this.certId = certId;
if (certStatus == null)
{
this.certStatus = new CertStatus();
}
else if (certStatus instanceof UnknownStatus)
{
this.certStatus = new CertStatus(2, DERNull.INSTANCE);
}
else
{
RevokedStatus rs = (RevokedStatus)certStatus;
if (rs.hasRevocationReason())
{
this.certStatus = new CertStatus(
new RevokedInfo(new ASN1GeneralizedTime(rs.getRevocationTime()), CRLReason.lookup(rs.getRevocationReason())));
}
else
{
this.certStatus = new CertStatus(
new RevokedInfo(new ASN1GeneralizedTime(rs.getRevocationTime()), null));
}
}
this.thisUpdate = new DERGeneralizedTime(thisUpdate);
if (nextUpdate != null)
{
this.nextUpdate = new DERGeneralizedTime(nextUpdate);
}
else
{
this.nextUpdate = null;
}
this.extensions = extensions;
}
public SingleResponse toResponse()
throws Exception
{
return new SingleResponse(certId.toASN1Primitive(), certStatus, thisUpdate, nextUpdate, extensions);
}
}
/**
* basic constructor
*/
public BasicOCSPRespBuilder(
RespID responderID)
{
this.responderID = responderID;
}
/**
* construct with the responderID to be the SHA-1 keyHash of the passed in public key.
*
* @param key the key info of the responder public key.
* @param digCalc a SHA-1 digest calculator
*/
public BasicOCSPRespBuilder(
SubjectPublicKeyInfo key,
DigestCalculator digCalc)
throws OCSPException
{
this.responderID = new RespID(key, digCalc);
}
/**
* Add a response for a particular Certificate ID.
*
* @param certID certificate ID details
* @param certStatus status of the certificate - null if okay
*/
public BasicOCSPRespBuilder addResponse(
CertificateID certID,
CertificateStatus certStatus)
{
this.addResponse(certID, certStatus, new Date(), null, null);
return this;
}
/**
* Add a response for a particular Certificate ID.
*
* @param certID certificate ID details
* @param certStatus status of the certificate - null if okay
* @param singleExtensions optional extensions
*/
public BasicOCSPRespBuilder addResponse(
CertificateID certID,
CertificateStatus certStatus,
Extensions singleExtensions)
{
this.addResponse(certID, certStatus, new Date(), null, singleExtensions);
return this;
}
/**
* Add a response for a particular Certificate ID.
*
* @param certID certificate ID details
* @param nextUpdate date when next update should be requested
* @param certStatus status of the certificate - null if okay
* @param singleExtensions optional extensions
*/
public BasicOCSPRespBuilder addResponse(
CertificateID certID,
CertificateStatus certStatus,
Date nextUpdate,
Extensions singleExtensions)
{
this.addResponse(certID, certStatus, new Date(), nextUpdate, singleExtensions);
return this;
}
/**
* Add a response for a particular Certificate ID.
*
* @param certID certificate ID details
* @param thisUpdate date this response was valid on
* @param nextUpdate date when next update should be requested
* @param certStatus status of the certificate - null if okay
*/
public BasicOCSPRespBuilder addResponse(
CertificateID certID,
CertificateStatus certStatus,
Date thisUpdate,
Date nextUpdate)
{
this.addResponse(certID, certStatus, thisUpdate, nextUpdate, null);
return this;
}
/**
* Add a response for a particular Certificate ID.
*
* @param certID certificate ID details
* @param thisUpdate date this response was valid on
* @param nextUpdate date when next update should be requested
* @param certStatus status of the certificate - null if okay
* @param singleExtensions optional extensions
*/
public BasicOCSPRespBuilder addResponse(
CertificateID certID,
CertificateStatus certStatus,
Date thisUpdate,
Date nextUpdate,
Extensions singleExtensions)
{
list.add(new ResponseObject(certID, certStatus, thisUpdate, nextUpdate, singleExtensions));
return this;
}
/**
* Set the extensions for the response.
*
* @param responseExtensions the extension object to carry.
*/
public BasicOCSPRespBuilder setResponseExtensions(
Extensions responseExtensions)
{
this.responseExtensions = responseExtensions;
return this;
}
public BasicOCSPResp build(
ContentSigner signer,
X509CertificateHolder[] chain,
Date producedAt)
throws OCSPException
{
Iterator it = list.iterator();
ASN1EncodableVector responses = new ASN1EncodableVector();
while (it.hasNext())
{
try
{
responses.add(((ResponseObject)it.next()).toResponse());
}
catch (Exception e)
{
throw new OCSPException("exception creating Request", e);
}
}
ResponseData tbsResp = new ResponseData(responderID.toASN1Primitive(), new ASN1GeneralizedTime(producedAt), new DERSequence(responses), responseExtensions);
DERBitString bitSig;
try
{
OutputStream sigOut = signer.getOutputStream();
sigOut.write(tbsResp.getEncoded(ASN1Encoding.DER));
sigOut.close();
bitSig = new DERBitString(signer.getSignature());
}
catch (Exception e)
{
throw new OCSPException("exception processing TBSRequest: " + e.getMessage(), e);
}
AlgorithmIdentifier sigAlgId = signer.getAlgorithmIdentifier();
DERSequence chainSeq = null;
if (chain != null && chain.length > 0)
{
ASN1EncodableVector v = new ASN1EncodableVector();
for (int i = 0; i != chain.length; i++)
{
v.add(chain[i].toASN1Structure());
}
chainSeq = new DERSequence(v);
}
return new BasicOCSPResp(new BasicOCSPResponse(tbsResp, sigAlgId, bitSig, chainSeq));
}
}