From 81718ad166d0dd458ed070e753d1f4bfcc40593d Mon Sep 17 00:00:00 2001 From: Peter Dettman Date: Sun, 26 May 2024 17:22:18 +0700 Subject: Auto-adjust DateTime precision for GeneralizedTime in X.509 (and OCSP) - see https://github.com/bcgit/bc-csharp/issues/474 --- crypto/src/asn1/cms/Time.cs | 5 ++-- crypto/src/asn1/esf/CrlIdentifier.cs | 2 +- crypto/src/asn1/esf/OcspIdentifier.cs | 7 ++---- crypto/src/asn1/x509/Rfc5280Asn1Utilities.cs | 14 +++++++++++ crypto/src/asn1/x509/Time.cs | 4 ++-- crypto/src/ocsp/BasicOCSPRespGenerator.cs | 27 +++++++++++++--------- crypto/src/ocsp/RevokedStatus.cs | 8 +++++-- crypto/src/tsp/TimeStampTokenGenerator.cs | 7 +++++- .../x509/X509V2AttributeCertificateGenerator.cs | 4 ++-- crypto/src/x509/X509V2CRLGenerator.cs | 2 +- 10 files changed, 53 insertions(+), 27 deletions(-) create mode 100644 crypto/src/asn1/x509/Rfc5280Asn1Utilities.cs (limited to 'crypto/src') diff --git a/crypto/src/asn1/cms/Time.cs b/crypto/src/asn1/cms/Time.cs index f41433ddd..66fa578af 100644 --- a/crypto/src/asn1/cms/Time.cs +++ b/crypto/src/asn1/cms/Time.cs @@ -1,6 +1,7 @@ using System; using System.Globalization; +using Org.BouncyCastle.Asn1.X509; using Org.BouncyCastle.Utilities; namespace Org.BouncyCastle.Asn1.Cms @@ -56,11 +57,11 @@ namespace Org.BouncyCastle.Asn1.Cms if (utc.Year < 1950 || utc.Year > 2049) { - m_timeObject = new DerGeneralizedTime(utc); + m_timeObject = Rfc5280Asn1Utilities.CreateGeneralizedTime(utc); } else { - m_timeObject = new DerUtcTime(utc, 2049); + m_timeObject = Rfc5280Asn1Utilities.CreateUtcTime(utc); } } diff --git a/crypto/src/asn1/esf/CrlIdentifier.cs b/crypto/src/asn1/esf/CrlIdentifier.cs index 7d6225c63..9521d6a08 100644 --- a/crypto/src/asn1/esf/CrlIdentifier.cs +++ b/crypto/src/asn1/esf/CrlIdentifier.cs @@ -62,7 +62,7 @@ namespace Org.BouncyCastle.Asn1.Esf } public CrlIdentifier(X509Name crlIssuer, DateTime crlIssuedTime, BigInteger crlNumber) - : this(crlIssuer, new Asn1UtcTime(crlIssuedTime, 2049), crlNumber) + : this(crlIssuer, Rfc5280Asn1Utilities.CreateUtcTime(crlIssuedTime), crlNumber) { } diff --git a/crypto/src/asn1/esf/OcspIdentifier.cs b/crypto/src/asn1/esf/OcspIdentifier.cs index fa7069aed..fa3d60291 100644 --- a/crypto/src/asn1/esf/OcspIdentifier.cs +++ b/crypto/src/asn1/esf/OcspIdentifier.cs @@ -1,6 +1,7 @@ using System; using Org.BouncyCastle.Asn1.Ocsp; +using Org.BouncyCastle.Asn1.X509; using Org.BouncyCastle.Utilities; namespace Org.BouncyCastle.Asn1.Esf @@ -50,12 +51,8 @@ namespace Org.BouncyCastle.Asn1.Esf } public OcspIdentifier(ResponderID ocspResponderID, DateTime producedAt) + : this(ocspResponderID, Rfc5280Asn1Utilities.CreateGeneralizedTime(producedAt)) { - if (ocspResponderID == null) - throw new ArgumentNullException(nameof(ocspResponderID)); - - this.ocspResponderID = ocspResponderID; - this.producedAt = new Asn1GeneralizedTime(producedAt); } public OcspIdentifier(ResponderID ocspResponderID, Asn1GeneralizedTime producedAt) diff --git a/crypto/src/asn1/x509/Rfc5280Asn1Utilities.cs b/crypto/src/asn1/x509/Rfc5280Asn1Utilities.cs new file mode 100644 index 000000000..899236609 --- /dev/null +++ b/crypto/src/asn1/x509/Rfc5280Asn1Utilities.cs @@ -0,0 +1,14 @@ +using System; + +using Org.BouncyCastle.Utilities.Date; + +namespace Org.BouncyCastle.Asn1.X509 +{ + internal class Rfc5280Asn1Utilities + { + internal static DerGeneralizedTime CreateGeneralizedTime(DateTime dateTime) => + new DerGeneralizedTime(DateTimeUtilities.WithPrecisionSecond(dateTime)); + + internal static DerUtcTime CreateUtcTime(DateTime dateTime) => new DerUtcTime(dateTime, 2049); + } +} diff --git a/crypto/src/asn1/x509/Time.cs b/crypto/src/asn1/x509/Time.cs index 99d141c43..e504d0573 100644 --- a/crypto/src/asn1/x509/Time.cs +++ b/crypto/src/asn1/x509/Time.cs @@ -56,11 +56,11 @@ namespace Org.BouncyCastle.Asn1.X509 if (utc.Year < 1950 || utc.Year > 2049) { - m_timeObject = new DerGeneralizedTime(utc); + m_timeObject = Rfc5280Asn1Utilities.CreateGeneralizedTime(utc); } else { - m_timeObject = new DerUtcTime(utc, 2049); + m_timeObject = Rfc5280Asn1Utilities.CreateUtcTime(utc); } } diff --git a/crypto/src/ocsp/BasicOCSPRespGenerator.cs b/crypto/src/ocsp/BasicOCSPRespGenerator.cs index 3d89dfd38..a10a49fad 100644 --- a/crypto/src/ocsp/BasicOCSPRespGenerator.cs +++ b/crypto/src/ocsp/BasicOCSPRespGenerator.cs @@ -27,8 +27,8 @@ namespace Org.BouncyCastle.Ocsp { internal CertificateID certId; internal CertStatus certStatus; - internal Asn1GeneralizedTime thisUpdate; - internal Asn1GeneralizedTime nextUpdate; + internal DerGeneralizedTime thisUpdate; + internal DerGeneralizedTime nextUpdate; internal X509Extensions extensions; internal ResponseObject( @@ -55,12 +55,14 @@ namespace Org.BouncyCastle.Ocsp ? new CrlReason(rs.RevocationReason) : null; - this.certStatus = new CertStatus( - new RevokedInfo(new Asn1GeneralizedTime(rs.RevocationTime), revocationReason)); + var revocationTime = Rfc5280Asn1Utilities.CreateGeneralizedTime(rs.RevocationTime); + var revokedInfo = new RevokedInfo(revocationTime, revocationReason); + + this.certStatus = new CertStatus(revokedInfo); } - this.thisUpdate = new DerGeneralizedTime(thisUpdate); - this.nextUpdate = nextUpdate.HasValue ? new DerGeneralizedTime(nextUpdate.Value) : null; + this.thisUpdate = Rfc5280Asn1Utilities.CreateGeneralizedTime(thisUpdate); + this.nextUpdate = nextUpdate.HasValue ? Rfc5280Asn1Utilities.CreateGeneralizedTime(nextUpdate.Value) : null; this.extensions = extensions; } @@ -69,12 +71,12 @@ namespace Org.BouncyCastle.Ocsp { return new SingleResponse(certId.ToAsn1Object(), certStatus, thisUpdate, nextUpdate, extensions); } - } + } - /** + /** * basic constructor */ - public BasicOcspRespGenerator( + public BasicOcspRespGenerator( RespID responderID) { this.responderID = responderID; @@ -184,8 +186,11 @@ namespace Org.BouncyCastle.Ocsp } } - var responseData = new ResponseData(responderID.ToAsn1Object(), new Asn1GeneralizedTime(producedAt), - new DerSequence(responses), responseExtensions); + var responseData = new ResponseData( + responderID.ToAsn1Object(), + Rfc5280Asn1Utilities.CreateGeneralizedTime(producedAt), + new DerSequence(responses), + responseExtensions); DerBitString bitSig; try diff --git a/crypto/src/ocsp/RevokedStatus.cs b/crypto/src/ocsp/RevokedStatus.cs index a37bdade9..14df6b2ea 100644 --- a/crypto/src/ocsp/RevokedStatus.cs +++ b/crypto/src/ocsp/RevokedStatus.cs @@ -19,12 +19,16 @@ namespace Org.BouncyCastle.Ocsp public RevokedStatus(DateTime revocationDate) { - m_revokedInfo = new RevokedInfo(new Asn1GeneralizedTime(revocationDate)); + var revocationTime = Rfc5280Asn1Utilities.CreateGeneralizedTime(revocationDate); + + m_revokedInfo = new RevokedInfo(revocationTime); } public RevokedStatus(DateTime revocationDate, int reason) { - m_revokedInfo = new RevokedInfo(new Asn1GeneralizedTime(revocationDate), new CrlReason(reason)); + var revocationTime = Rfc5280Asn1Utilities.CreateGeneralizedTime(revocationDate); + + m_revokedInfo = new RevokedInfo(revocationTime, new CrlReason(reason)); } public DateTime RevocationTime diff --git a/crypto/src/tsp/TimeStampTokenGenerator.cs b/crypto/src/tsp/TimeStampTokenGenerator.cs index f304a0faf..13c9605a9 100644 --- a/crypto/src/tsp/TimeStampTokenGenerator.cs +++ b/crypto/src/tsp/TimeStampTokenGenerator.cs @@ -340,7 +340,12 @@ namespace Org.BouncyCastle.Tsp respExtensions = extGen.Generate(); } - var timeStampTime = new Asn1GeneralizedTime(WithResolution(genTime, resolution)); + /* + * RFC 3161. The ASN.1 GeneralizedTime syntax can include fraction-of-second details. Such syntax, without + * the restrictions from RFC 2459 Section 4.1.2.5.2, where GeneralizedTime is limited to represent the + * time with a granularity of one second, may be used here. + */ + var timeStampTime = new DerGeneralizedTime(WithResolution(genTime, resolution)); TstInfo tstInfo = new TstInfo(tsaPolicy, messageImprint, new DerInteger(serialNumber), timeStampTime, accuracy, diff --git a/crypto/src/x509/X509V2AttributeCertificateGenerator.cs b/crypto/src/x509/X509V2AttributeCertificateGenerator.cs index 954776b43..f747f2d14 100644 --- a/crypto/src/x509/X509V2AttributeCertificateGenerator.cs +++ b/crypto/src/x509/X509V2AttributeCertificateGenerator.cs @@ -51,13 +51,13 @@ namespace Org.BouncyCastle.X509 public void SetNotBefore( DateTime date) { - acInfoGen.SetStartDate(new Asn1GeneralizedTime(date)); + acInfoGen.SetStartDate(Rfc5280Asn1Utilities.CreateGeneralizedTime(date)); } public void SetNotAfter( DateTime date) { - acInfoGen.SetEndDate(new Asn1GeneralizedTime(date)); + acInfoGen.SetEndDate(Rfc5280Asn1Utilities.CreateGeneralizedTime(date)); } /// Add an attribute. diff --git a/crypto/src/x509/X509V2CRLGenerator.cs b/crypto/src/x509/X509V2CRLGenerator.cs index 358dc63de..c4ea990d2 100644 --- a/crypto/src/x509/X509V2CRLGenerator.cs +++ b/crypto/src/x509/X509V2CRLGenerator.cs @@ -112,7 +112,7 @@ namespace Org.BouncyCastle.X509 DateTime invalidityDate) { tbsGen.AddCrlEntry(new DerInteger(userCertificate), new Time(revocationDate), reason, - new Asn1GeneralizedTime(invalidityDate)); + Rfc5280Asn1Utilities.CreateGeneralizedTime(invalidityDate)); } /** -- cgit 1.4.1