summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--crypto/Readme.html1
-rw-r--r--crypto/src/asn1/cms/Time.cs5
-rw-r--r--crypto/src/asn1/esf/CrlIdentifier.cs2
-rw-r--r--crypto/src/asn1/esf/OcspIdentifier.cs7
-rw-r--r--crypto/src/asn1/x509/Rfc5280Asn1Utilities.cs14
-rw-r--r--crypto/src/asn1/x509/Time.cs4
-rw-r--r--crypto/src/ocsp/BasicOCSPRespGenerator.cs27
-rw-r--r--crypto/src/ocsp/RevokedStatus.cs8
-rw-r--r--crypto/src/tsp/TimeStampTokenGenerator.cs7
-rw-r--r--crypto/src/x509/X509V2AttributeCertificateGenerator.cs4
-rw-r--r--crypto/src/x509/X509V2CRLGenerator.cs2
11 files changed, 54 insertions, 27 deletions
diff --git a/crypto/Readme.html b/crypto/Readme.html
index 3c5a451b4..81e26814e 100644
--- a/crypto/Readme.html
+++ b/crypto/Readme.html
@@ -342,6 +342,7 @@
         <h5>Additional Features and Functionality</h5>
         <ul>
             <li>Embed Picnic and Sike data in source to make it trim-friendly.</li>
+            <li>Auto-adjust DateTime precision for GeneralizedTime in X.509 (and OCSP).</li>
         </ul>
         <h5>Additional Notes</h5>
         <ul>
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));
 		}
 
 		/// <summary>Add an attribute.</summary>
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));
 		}
 
 		/**