diff options
Diffstat (limited to 'Crypto/src/tsp/TimeStampResponseGenerator.cs')
-rw-r--r-- | Crypto/src/tsp/TimeStampResponseGenerator.cs | 210 |
1 files changed, 210 insertions, 0 deletions
diff --git a/Crypto/src/tsp/TimeStampResponseGenerator.cs b/Crypto/src/tsp/TimeStampResponseGenerator.cs new file mode 100644 index 000000000..8d798de67 --- /dev/null +++ b/Crypto/src/tsp/TimeStampResponseGenerator.cs @@ -0,0 +1,210 @@ +using System; +using System.Collections; +using System.IO; + +using Org.BouncyCastle.Asn1; +using Org.BouncyCastle.Asn1.Cmp; +using Org.BouncyCastle.Asn1.Cms; +using Org.BouncyCastle.Asn1.Tsp; +using Org.BouncyCastle.Math; +using Org.BouncyCastle.Utilities.Date; + +namespace Org.BouncyCastle.Tsp +{ + /** + * Generator for RFC 3161 Time Stamp Responses. + */ + public class TimeStampResponseGenerator + { + private PkiStatus status; + + private Asn1EncodableVector statusStrings; + + private int failInfo; + private TimeStampTokenGenerator tokenGenerator; + private IList acceptedAlgorithms; + private IList acceptedPolicies; + private IList acceptedExtensions; + + public TimeStampResponseGenerator( + TimeStampTokenGenerator tokenGenerator, + IList acceptedAlgorithms) + : this(tokenGenerator, acceptedAlgorithms, null, null) + { + } + + public TimeStampResponseGenerator( + TimeStampTokenGenerator tokenGenerator, + IList acceptedAlgorithms, + IList acceptedPolicy) + : this(tokenGenerator, acceptedAlgorithms, acceptedPolicy, null) + { + } + + public TimeStampResponseGenerator( + TimeStampTokenGenerator tokenGenerator, + IList acceptedAlgorithms, + IList acceptedPolicies, + IList acceptedExtensions) + { + this.tokenGenerator = tokenGenerator; + this.acceptedAlgorithms = acceptedAlgorithms; + this.acceptedPolicies = acceptedPolicies; + this.acceptedExtensions = acceptedExtensions; + + statusStrings = new Asn1EncodableVector(); + } + + private void AddStatusString(string statusString) + { + statusStrings.Add(new DerUtf8String(statusString)); + } + + private void SetFailInfoField(int field) + { + failInfo |= field; + } + + private PkiStatusInfo GetPkiStatusInfo() + { + Asn1EncodableVector v = new Asn1EncodableVector( + new DerInteger((int)status)); + + if (statusStrings.Count > 0) + { + v.Add(new PkiFreeText(new DerSequence(statusStrings))); + } + + if (failInfo != 0) + { + v.Add(new FailInfo(failInfo)); + } + + return new PkiStatusInfo(new DerSequence(v)); + } + + public TimeStampResponse Generate( + TimeStampRequest request, + BigInteger serialNumber, + DateTime genTime) + { + return Generate(request, serialNumber, new DateTimeObject(genTime)); + } + + /** + * Return an appropriate TimeStampResponse. + * <p> + * If genTime is null a timeNotAvailable error response will be returned. + * + * @param request the request this response is for. + * @param serialNumber serial number for the response token. + * @param genTime generation time for the response token. + * @param provider provider to use for signature calculation. + * @return + * @throws NoSuchAlgorithmException + * @throws NoSuchProviderException + * @throws TSPException + * </p> + */ + public TimeStampResponse Generate( + TimeStampRequest request, + BigInteger serialNumber, + DateTimeObject genTime) + { + TimeStampResp resp; + + try + { + if (genTime == null) + throw new TspValidationException("The time source is not available.", + PkiFailureInfo.TimeNotAvailable); + + request.Validate(acceptedAlgorithms, acceptedPolicies, acceptedExtensions); + + this.status = PkiStatus.Granted; + this.AddStatusString("Operation Okay"); + + PkiStatusInfo pkiStatusInfo = GetPkiStatusInfo(); + + ContentInfo tstTokenContentInfo; + try + { + TimeStampToken token = tokenGenerator.Generate(request, serialNumber, genTime.Value); + byte[] encoded = token.ToCmsSignedData().GetEncoded(); + + tstTokenContentInfo = ContentInfo.GetInstance(Asn1Object.FromByteArray(encoded)); + } + catch (IOException e) + { + throw new TspException("Timestamp token received cannot be converted to ContentInfo", e); + } + + resp = new TimeStampResp(pkiStatusInfo, tstTokenContentInfo); + } + catch (TspValidationException e) + { + status = PkiStatus.Rejection; + + this.SetFailInfoField(e.FailureCode); + this.AddStatusString(e.Message); + + PkiStatusInfo pkiStatusInfo = GetPkiStatusInfo(); + + resp = new TimeStampResp(pkiStatusInfo, null); + } + + try + { + return new TimeStampResponse(resp); + } + catch (IOException e) + { + throw new TspException("created badly formatted response!", e); + } + } + + class FailInfo + : DerBitString + { + internal FailInfo( + int failInfoValue) + : base(GetBytes(failInfoValue), GetPadBits(failInfoValue)) + { + } + } + + /** + * Generate a TimeStampResponse with chosen status and FailInfoField. + * + * @param status the PKIStatus to set. + * @param failInfoField the FailInfoField to set. + * @param statusString an optional string describing the failure. + * @return a TimeStampResponse with a failInfoField and optional statusString + * @throws TSPException in case the response could not be created + */ + public TimeStampResponse GenerateFailResponse(PkiStatus status, int failInfoField, string statusString) + { + this.status = status; + + this.SetFailInfoField(failInfoField); + + if (statusString != null) + { + this.AddStatusString(statusString); + } + + PkiStatusInfo pkiStatusInfo = GetPkiStatusInfo(); + + TimeStampResp resp = new TimeStampResp(pkiStatusInfo, null); + + try + { + return new TimeStampResponse(resp); + } + catch (IOException e) + { + throw new TspException("created badly formatted response!", e); + } + } + } +} |