コード例 #1
0
		/// <summary>Constructor</summary>
		/// <param name="forward">Certificate from the other CA to this CA.</param>
		/// <param name="reverse">Certificate from this CA to the other CA.</param>
		public X509CertificatePair(
			X509Certificate	forward,
			X509Certificate	reverse)
		{
			this.forward = forward;
			this.reverse = reverse;
		}
コード例 #2
0
		/**
		 * basic creation - only the default attributes will be included here.
		 */
		public TimeStampTokenGenerator(
			AsymmetricKeyParameter	key,
			X509Certificate			cert,
			string					digestOID,
			string					tsaPolicyOID)
			: this(key, cert, digestOID, tsaPolicyOID, null, null)
		{
		}
コード例 #3
0
		/**
		 * create from an issuer certificate and the serial number of the
		 * certificate it signed.
		 * @exception OcspException if any problems occur creating the id fields.
		 */
		public CertificateID(
			string			hashAlgorithm,
			X509Certificate	issuerCert,
			BigInteger		serialNumber)
		{
			AlgorithmIdentifier hashAlg = new AlgorithmIdentifier(
				new DerObjectIdentifier(hashAlgorithm), DerNull.Instance);

			this.id = createCertID(hashAlg, issuerCert, new DerInteger(serialNumber));
		}
コード例 #4
0
		/// <summary>Constructor from a ASN.1 CertificatePair structure.</summary>
		/// <param name="pair">The <c>CertificatePair</c> ASN.1 object.</param>
		public X509CertificatePair(
			CertificatePair pair)
		{
			if (pair.Forward != null)
			{
				this.forward = new X509Certificate(pair.Forward);
			}
			if (pair.Reverse != null)
			{
				this.reverse = new X509Certificate(pair.Reverse);
			}
		}
コード例 #5
0
		/**
		 * create with a signer with extra signed/unsigned attributes.
		 */
		public TimeStampTokenGenerator(
			AsymmetricKeyParameter	key,
			X509Certificate			cert,
			string					digestOID,
			string					tsaPolicyOID,
			Asn1.Cms.AttributeTable	signedAttr,
			Asn1.Cms.AttributeTable	unsignedAttr)
		{
			this.key = key;
			this.cert = cert;
			this.digestOID = digestOID;
			this.tsaPolicyOID = tsaPolicyOID;
			this.unsignedAttr = unsignedAttr;

			TspUtil.ValidateCertificate(cert);

			//
			// Add the ESSCertID attribute
			//
			IDictionary signedAttrs;
			if (signedAttr != null)
			{
				signedAttrs = signedAttr.ToDictionary();
			}
			else
			{
				signedAttrs = Platform.CreateHashtable();
			}

			try
			{
				byte[] hash = DigestUtilities.CalculateDigest("SHA-1", cert.GetEncoded());

				EssCertID essCertid = new EssCertID(hash);

				Asn1.Cms.Attribute attr = new Asn1.Cms.Attribute(
					PkcsObjectIdentifiers.IdAASigningCertificate,
					new DerSet(new SigningCertificate(essCertid)));

				signedAttrs[attr.AttrType] = attr;
			}
			catch (CertificateEncodingException e)
			{
				throw new TspException("Exception processing certificate.", e);
			}
			catch (SecurityUtilityException e)
			{
				throw new TspException("Can't find a SHA-1 implementation.", e);
			}

			this.signedAttr = new Asn1.Cms.AttributeTable(signedAttrs);
		}
コード例 #6
0
		/// <summary>
		/// Creates an instance of TrustAnchor with the specified X509Certificate and
	    /// optional name constraints, which are intended to be used as additional
	    /// constraints when validating an X.509 certification path.
	    ///	The name constraints are specified as a byte array. This byte array
	    ///	should contain the DER encoded form of the name constraints, as they
	    ///	would appear in the NameConstraints structure defined in RFC 2459 and
	    ///	X.509. The ASN.1 definition of this structure appears below.
	    ///	
	    ///	<pre>
	    ///	NameConstraints ::= SEQUENCE {
	    ///		permittedSubtrees       [0]     GeneralSubtrees OPTIONAL,
	    ///		excludedSubtrees        [1]     GeneralSubtrees OPTIONAL }
	    ///	   
        /// GeneralSubtrees ::= SEQUENCE SIZE (1..MAX) OF GeneralSubtree
        /// 
        ///		GeneralSubtree ::= SEQUENCE {
        ///		base                    GeneralName,
        ///		minimum         [0]     BaseDistance DEFAULT 0,
        ///		maximum         [1]     BaseDistance OPTIONAL }
        ///		
        ///		BaseDistance ::= INTEGER (0..MAX)
		///
		///		GeneralName ::= CHOICE {
		///		otherName                       [0]     OtherName,
		///		rfc822Name                      [1]     IA5String,
		///		dNSName                         [2]     IA5String,
		///		x400Address                     [3]     ORAddress,
		///		directoryName                   [4]     Name,
		///		ediPartyName                    [5]     EDIPartyName,
		///		uniformResourceIdentifier       [6]     IA5String,
		///		iPAddress                       [7]     OCTET STRING,
		///		registeredID                    [8]     OBJECT IDENTIFIER}
		///	</pre>
		///	
		///	Note that the name constraints byte array supplied is cloned to protect
		///	against subsequent modifications.
		/// </summary>
		/// <param name="trustedCert">a trusted X509Certificate</param>
		/// <param name="nameConstraints">a byte array containing the ASN.1 DER encoding of a
		/// NameConstraints extension to be used for checking name
		/// constraints. Only the value of the extension is included, not
		/// the OID or criticality flag. Specify null to omit the
		/// parameter.</param>
		/// <exception cref="ArgumentNullException">if the specified X509Certificate is null</exception>
		public TrustAnchor(
			X509Certificate	trustedCert,
			byte[]			nameConstraints)
		{
			if (trustedCert == null)
				throw new ArgumentNullException("trustedCert");

			this.trustedCert = trustedCert;
			this.pubKey = null;
			this.caName = null;
			this.caPrincipal = null;
			setNameConstraints(nameConstraints);
		}
コード例 #7
0
		/// <summary>Return the subject of the given cert as an X509Principal.</summary>
		public static X509Name GetSubjectX509Principal(
			X509Certificate cert)
		{
			try
			{
				TbsCertificateStructure tbsCert = TbsCertificateStructure.GetInstance(
					Asn1Object.FromByteArray(cert.GetTbsCertificate()));

				return tbsCert.Subject;
			}
			catch (Exception e)
			{
				throw new CertificateEncodingException("Could not extract subject", e);
			}
		}
コード例 #8
0
		public AttributeCertificateHolder(
			X509Certificate	cert)
		{
			X509Name name;
			try
			{
				name = PrincipalUtilities.GetIssuerX509Principal(cert);
			}
			catch (Exception e)
			{
				throw new CertificateParsingException(e.Message);
			}

			holder = new Holder(new IssuerSerial(GenerateGeneralNames(name), new DerInteger(cert.SerialNumber)));
		}
コード例 #9
0
		public X509CrlStoreSelector(
			X509CrlStoreSelector o)
		{
			this.certificateChecking = o.CertificateChecking;
			this.dateAndTime = o.DateAndTime;
			this.issuers = o.Issuers;
			this.maxCrlNumber = o.MaxCrlNumber;
			this.minCrlNumber = o.MinCrlNumber;

			this.deltaCrlIndicatorEnabled = o.DeltaCrlIndicatorEnabled;
			this.completeCrlEnabled = o.CompleteCrlEnabled;
			this.maxBaseCrlNumber = o.MaxBaseCrlNumber;
			this.attrCertChecking = o.AttrCertChecking;
			this.issuingDistributionPointEnabled = o.IssuingDistributionPointEnabled;
			this.issuingDistributionPoint = o.IssuingDistributionPoint;
		}
コード例 #10
0
        public string GetCertificateAlias(X509Certificate cert)
        {
            if (cert == null)
            {
                throw new ArgumentNullException("cert");
            }

            foreach (DictionaryEntry entry in _certs)
            {
                var entryValue = (X509CertificateEntry) entry.Value;
                if (entryValue.Certificate.Equals(cert))
                {
                    return (string) entry.Key;
                }
            }

            foreach (DictionaryEntry entry in _keyCerts)
            {
                var entryValue = (X509CertificateEntry) entry.Value;
                if (entryValue.Certificate.Equals(cert))
                {
                    return (string) entry.Key;
                }
            }

            return null;
        }
コード例 #11
0
		/// <summary>
		/// Creates an instance of <c>TrustAnchor</c> where the
		/// most-trusted CA is specified as an X500Principal and public key.
		/// </summary>
		/// <remarks>
		/// <p>
		/// Name constraints are an optional parameter, and are intended to be used
		/// as additional constraints when validating an X.509 certification path.
		/// </p><p>
		/// The name constraints are specified as a byte array. This byte array
		/// contains the DER encoded form of the name constraints, as they
		/// would appear in the NameConstraints structure defined in RFC 2459
		/// and X.509. The ASN.1 notation for this structure is supplied in the
		/// documentation for the other constructors.
		/// </p><p>
		/// Note that the name constraints byte array supplied here is cloned to
		/// protect against subsequent modifications.
		/// </p>
		/// </remarks>
		/// <param name="caPrincipal">the name of the most-trusted CA as X509Name</param>
		/// <param name="pubKey">the public key of the most-trusted CA</param>
		/// <param name="nameConstraints">
		/// a byte array containing the ASN.1 DER encoding of a NameConstraints extension to
		/// be used for checking name constraints. Only the value of the extension is included,
		/// not the OID or criticality flag. Specify <c>null</c> to omit the parameter.
		/// </param>
		/// <exception cref="ArgumentNullException">
		/// if <c>caPrincipal</c> or <c>pubKey</c> is null
		/// </exception>
		public TrustAnchor(
			X509Name				caPrincipal,
			AsymmetricKeyParameter	pubKey,
			byte[]					nameConstraints) 
		{
			if (caPrincipal == null)
				throw new ArgumentNullException("caPrincipal");
			if (pubKey == null)
				throw new ArgumentNullException("pubKey");

			this.trustedCert = null;
			this.caPrincipal = caPrincipal;
			this.caName = caPrincipal.ToString();
			this.pubKey = pubKey;
			setNameConstraints(nameConstraints);
		}
コード例 #12
0
		private OcspReq GenerateRequest(
			DerObjectIdentifier		signingAlgorithm,
			AsymmetricKeyParameter	privateKey,
			X509Certificate[]		chain,
			SecureRandom			random)
		{
			Asn1EncodableVector requests = new Asn1EncodableVector();

			foreach (RequestObject reqObj in list)
			{
				try
				{
					requests.Add(reqObj.ToRequest());
				}
				catch (Exception e)
				{
					throw new OcspException("exception creating Request", e);
				}
			}

			TbsRequest tbsReq = new TbsRequest(requestorName, new DerSequence(requests), requestExtensions);

			ISigner sig = null;
			Signature signature = null;

			if (signingAlgorithm != null)
			{
				if (requestorName == null)
				{
					throw new OcspException("requestorName must be specified if request is signed.");
				}

				try
				{
					sig = SignerUtilities.GetSigner(signingAlgorithm.Id);
					if (random != null)
					{
						sig.Init(true, new ParametersWithRandom(privateKey, random));
					}
					else
					{
						sig.Init(true, privateKey);
					}
				}
				catch (Exception e)
				{
					throw new OcspException("exception creating signature: " + e, e);
				}

				DerBitString bitSig = null;

				try
				{
					byte[] encoded = tbsReq.GetEncoded();
					sig.BlockUpdate(encoded, 0, encoded.Length);

					bitSig = new DerBitString(sig.GenerateSignature());
				}
				catch (Exception e)
				{
					throw new OcspException("exception processing TBSRequest: " + e, e);
				}

				AlgorithmIdentifier sigAlgId = new AlgorithmIdentifier(signingAlgorithm, DerNull.Instance);

				if (chain != null && chain.Length > 0)
				{
					Asn1EncodableVector v = new Asn1EncodableVector();
					try
					{
						for (int i = 0; i != chain.Length; i++)
						{
							v.Add(
								X509CertificateStructure.GetInstance(
									Asn1Object.FromByteArray(chain[i].GetEncoded())));
						}
					}
					catch (IOException e)
					{
						throw new OcspException("error processing certs", e);
					}
					catch (CertificateEncodingException e)
					{
						throw new OcspException("error encoding certs", e);
					}

					signature = new Signature(sigAlgId, bitSig, new DerSequence(v));
				}
				else
				{
					signature = new Signature(sigAlgId, bitSig);
				}
			}

			return new OcspReq(new OcspRequest(tbsReq, signature));
		}
コード例 #13
0
		internal static void ProcessCertA(
			PkixCertPath			certPath,
			PkixParameters			paramsPKIX,
			int						index,
			AsymmetricKeyParameter	workingPublicKey,
			X509Name				workingIssuerName,
			X509Certificate			sign)
		{
			IList certs = certPath.Certificates;
			X509Certificate cert = (X509Certificate)certs[index];
			//
			// (a) verify
			//
			try
			{
				// (a) (1)
				//
				cert.Verify(workingPublicKey);
			}
			catch (GeneralSecurityException e)
			{
				throw new PkixCertPathValidatorException("Could not validate certificate signature.", e, certPath, index);
			}

			try
			{
				// (a) (2)
				//
				cert.CheckValidity(PkixCertPathValidatorUtilities
					.GetValidCertDateFromValidityModel(paramsPKIX, certPath, index));
			}
			catch (CertificateExpiredException e)
			{
				throw new PkixCertPathValidatorException("Could not validate certificate: " + e.Message, e, certPath, index);
			}
			catch (CertificateNotYetValidException e)
			{
				throw new PkixCertPathValidatorException("Could not validate certificate: " + e.Message, e, certPath, index);
			}
			catch (Exception e)
			{
				throw new PkixCertPathValidatorException("Could not validate time of certificate.", e, certPath, index);
			}

			//
			// (a) (3)
			//
			if (paramsPKIX.IsRevocationEnabled)
			{
				try
				{
					CheckCrls(paramsPKIX, cert, PkixCertPathValidatorUtilities.GetValidCertDateFromValidityModel(paramsPKIX,
						certPath, index), sign, workingPublicKey, certs);
				}
				catch (Exception e)
				{
					Exception cause = e.InnerException;
					if (cause == null)
					{
						cause = e;
					}
					throw new PkixCertPathValidatorException(e.Message, cause, certPath, index);
				}
			}

			//
			// (a) (4) name chaining
			//
			X509Name issuer = PkixCertPathValidatorUtilities.GetIssuerPrincipal(cert);
			if (!issuer.Equivalent(workingIssuerName, true))
			{
				throw new PkixCertPathValidatorException("IssuerName(" + issuer
					+ ") does not match SubjectName(" + workingIssuerName + ") of signing certificate.", null,
					certPath, index);
			}
		}
コード例 #14
0
		/**
		* Obtain and validate the certification path for the complete CRL issuer.
		* If a key usage extension is present in the CRL issuer's certificate,
		* verify that the cRLSign bit is set.
		*
		* @param crl                CRL which contains revocation information for the certificate
		*                           <code>cert</code>.
		* @param cert               The attribute certificate or certificate to check if it is
		*                           revoked.
		* @param defaultCRLSignCert The issuer certificate of the certificate <code>cert</code>.
		* @param defaultCRLSignKey  The public key of the issuer certificate
		*                           <code>defaultCRLSignCert</code>.
		* @param paramsPKIX         paramsPKIX PKIX parameters.
		* @param certPathCerts      The certificates on the certification path.
		* @return A <code>Set</code> with all keys of possible CRL issuer
		*         certificates.
		* @throws AnnotatedException if the CRL is not valid or the status cannot be checked or
		*                            some error occurs.
		*/
		internal static ISet ProcessCrlF(
			X509Crl					crl,
			object					cert,
			X509Certificate			defaultCRLSignCert,
			AsymmetricKeyParameter	defaultCRLSignKey,
			PkixParameters			paramsPKIX,
			IList					certPathCerts)
		{
			// (f)

			// get issuer from CRL
			X509CertStoreSelector selector = new X509CertStoreSelector();
			try
			{
				selector.Subject = crl.IssuerDN;
			}
			catch (IOException e)
			{
				throw new Exception(
					"Subject criteria for certificate selector to find issuer certificate for CRL could not be set.", e);
			}

			// get CRL signing certs
			IList coll = Platform.CreateArrayList();

			try
			{
                CollectionUtilities.AddRange(coll, PkixCertPathValidatorUtilities.FindCertificates(selector, paramsPKIX.GetStores()));
                CollectionUtilities.AddRange(coll, PkixCertPathValidatorUtilities.FindCertificates(selector, paramsPKIX.GetAdditionalStores()));
			}
			catch (Exception e)
			{
				throw new Exception("Issuer certificate for CRL cannot be searched.", e);
			}

			coll.Add(defaultCRLSignCert);

			IEnumerator cert_it = coll.GetEnumerator();

            IList validCerts = Platform.CreateArrayList();
            IList validKeys = Platform.CreateArrayList();

			while (cert_it.MoveNext())
			{
				X509Certificate signingCert = (X509Certificate)cert_it.Current;

				/*
				 * CA of the certificate, for which this CRL is checked, has also
				 * signed CRL, so skip the path validation, because is already done
				 */
				if (signingCert.Equals(defaultCRLSignCert))
				{
					validCerts.Add(signingCert);
					validKeys.Add(defaultCRLSignKey);
					continue;
				}
				try
				{
//					CertPathBuilder builder = CertPathBuilder.GetInstance("PKIX");
					PkixCertPathBuilder builder = new PkixCertPathBuilder();
					selector = new X509CertStoreSelector();
					selector.Certificate = signingCert;

					PkixParameters temp = (PkixParameters)paramsPKIX.Clone();
					temp.SetTargetCertConstraints(selector);

					PkixBuilderParameters parameters = (PkixBuilderParameters)
						PkixBuilderParameters.GetInstance(temp);

					/*
					 * if signingCert is placed not higher on the cert path a
					 * dependency loop results. CRL for cert is checked, but
					 * signingCert is needed for checking the CRL which is dependent
					 * on checking cert because it is higher in the cert path and so
					 * signing signingCert transitively. so, revocation is disabled,
					 * forgery attacks of the CRL are detected in this outer loop
					 * for all other it must be enabled to prevent forgery attacks
					 */
					if (certPathCerts.Contains(signingCert))
					{
						parameters.IsRevocationEnabled = false;
					}
					else
					{
						parameters.IsRevocationEnabled = true;
					}
					IList certs = builder.Build(parameters).CertPath.Certificates;
					validCerts.Add(signingCert);
					validKeys.Add(PkixCertPathValidatorUtilities.GetNextWorkingKey(certs, 0));
				}
				catch (PkixCertPathBuilderException e)
				{
					throw new Exception("Internal error.", e);
				}
				catch (PkixCertPathValidatorException e)
				{
					throw new Exception("Public key of issuer certificate of CRL could not be retrieved.", e);
				}
				//catch (Exception e)
				//{
				//    throw new Exception(e.Message);
				//}
			}

			ISet checkKeys = new HashSet();

			Exception lastException = null;
			for (int i = 0; i < validCerts.Count; i++)
			{
				X509Certificate signCert = (X509Certificate)validCerts[i];
				bool[] keyusage = signCert.GetKeyUsage();

				if (keyusage != null && (keyusage.Length < 7 || !keyusage[CRL_SIGN]))
				{
					lastException = new Exception(
						"Issuer certificate key usage extension does not permit CRL signing.");
				}
				else
				{
					checkKeys.Add(validKeys[i]);
				}
			}

			if ((checkKeys.Count == 0) && lastException == null)
			{
				throw new Exception("Cannot find a valid issuer certificate.");
			}
			if ((checkKeys.Count == 0) && lastException != null)
			{
				throw lastException;
			}

			return checkKeys;
		}
コード例 #15
0
		public OcspReq Generate(
			string					signingAlgorithm,
			AsymmetricKeyParameter	privateKey,
			X509Certificate[]		chain,
			SecureRandom			random)
		{
			if (signingAlgorithm == null)
				throw new ArgumentException("no signing algorithm specified");

			try
			{
				DerObjectIdentifier oid = OcspUtilities.GetAlgorithmOid(signingAlgorithm);

				return GenerateRequest(oid, privateKey, chain, random);
			}
			catch (ArgumentException)
			{
				throw new ArgumentException("unknown signing algorithm specified: " + signingAlgorithm);
			}
		}
コード例 #16
0
ファイル: OCSPReq.cs プロジェクト: Xanagandr/DisaOpenSource
		public X509Certificate[] GetCerts()
		{
			if (!this.IsSigned)
				return null;

			IList certs = this.GetCertList();
            X509Certificate[] result = new X509Certificate[certs.Count];
            for (int i = 0; i < certs.Count; ++i)
            {
                result[i] = (X509Certificate)certs[i];
            }
            return result;
		}
コード例 #17
0
		private PkixCertPathBuilderResult Build(
			IX509AttributeCertificate	attrCert,
			X509Certificate				tbvCert,
			PkixBuilderParameters		pkixParams,
			IList						tbvPath)
		{
			// If tbvCert is readily present in tbvPath, it indicates having run
			// into a cycle in the
			// PKI graph.
			if (tbvPath.Contains(tbvCert))
				return null;

			// step out, the certificate is not allowed to appear in a certification
			// chain
			if (pkixParams.GetExcludedCerts().Contains(tbvCert))
				return null;

			// test if certificate path exceeds maximum length
			if (pkixParams.MaxPathLength != -1)
			{
				if (tbvPath.Count - 1 > pkixParams.MaxPathLength)
					return null;
			}

			tbvPath.Add(tbvCert);

			PkixCertPathBuilderResult builderResult = null;

//			X509CertificateParser certParser = new X509CertificateParser();
			PkixAttrCertPathValidator validator = new PkixAttrCertPathValidator();

			try
			{
				// check whether the issuer of <tbvCert> is a TrustAnchor
				if (PkixCertPathValidatorUtilities.FindTrustAnchor(tbvCert, pkixParams.GetTrustAnchors()) != null)
				{
					PkixCertPath certPath = new PkixCertPath(tbvPath);
					PkixCertPathValidatorResult result;

					try
					{
						result = validator.Validate(certPath, pkixParams);
					}
					catch (Exception e)
					{
						throw new Exception("Certification path could not be validated.", e);
					}

					return new PkixCertPathBuilderResult(certPath, result.TrustAnchor,
						result.PolicyTree, result.SubjectPublicKey);
				}
				else
				{
					// add additional X.509 stores from locations in certificate
					try
					{
						PkixCertPathValidatorUtilities.AddAdditionalStoresFromAltNames(tbvCert, pkixParams);
					}
					catch (CertificateParsingException e)
					{
						throw new Exception("No additional X.509 stores can be added from certificate locations.", e);
					}

					// try to get the issuer certificate from one of the stores
					ISet issuers = new HashSet();
					try
					{
						issuers.AddAll(PkixCertPathValidatorUtilities.FindIssuerCerts(tbvCert, pkixParams));
					}
					catch (Exception e)
					{
						throw new Exception("Cannot find issuer certificate for certificate in certification path.", e);
					}

					if (issuers.IsEmpty)
						throw new Exception("No issuer certificate for certificate in certification path found.");

					foreach (X509Certificate issuer in issuers)
					{
						// if untrusted self signed certificate continue
						if (PkixCertPathValidatorUtilities.IsSelfIssued(issuer))
							continue;

						builderResult = Build(attrCert, issuer, pkixParams, tbvPath);

						if (builderResult != null)
							break;
					}
				}
			}
			catch (Exception e)
			{
				certPathException = new Exception("No valid certification path could be build.", e);
			}

			if (builderResult == null)
			{
				tbvPath.Remove(tbvCert);
			}

			return builderResult;
		}
コード例 #18
0
		/**
		 * Validate the time stamp token.
		 * <p>
		 * To be valid the token must be signed by the passed in certificate and
		 * the certificate must be the one referred to by the SigningCertificate
		 * attribute included in the hashed attributes of the token. The
		 * certificate must also have the ExtendedKeyUsageExtension with only
		 * KeyPurposeID.IdKPTimeStamping and have been valid at the time the
		 * timestamp was created.
		 * </p>
		 * <p>
		 * A successful call to validate means all the above are true.
		 * </p>
		 */
		public void Validate(
			X509Certificate cert)
		{
			try
			{
				byte[] hash = DigestUtilities.CalculateDigest(
					certID.GetHashAlgorithm(), cert.GetEncoded());

				if (!Arrays.ConstantTimeAreEqual(certID.GetCertHash(), hash))
				{
					throw new TspValidationException("certificate hash does not match certID hash.");
				}

				if (certID.IssuerSerial != null)
				{
					if (!certID.IssuerSerial.Serial.Value.Equals(cert.SerialNumber))
					{
						throw new TspValidationException("certificate serial number does not match certID for signature.");
					}

					GeneralName[] names = certID.IssuerSerial.Issuer.GetNames();
					X509Name principal = PrincipalUtilities.GetIssuerX509Principal(cert);
					bool found = false;

					for (int i = 0; i != names.Length; i++)
					{
						if (names[i].TagNo == 4
							&& X509Name.GetInstance(names[i].Name).Equivalent(principal))
						{
							found = true;
							break;
						}
					}

					if (!found)
					{
						throw new TspValidationException("certificate name does not match certID for signature. ");
					}
				}

				TspUtil.ValidateCertificate(cert);

				cert.CheckValidity(tstInfo.GenTime);

				if (!tsaSignerInfo.Verify(cert))
				{
					throw new TspValidationException("signature not created by certificate.");
				}
			}
			catch (CmsException e)
			{
				if (e.InnerException != null)
				{
					throw new TspException(e.Message, e.InnerException);
				}

				throw new TspException("CMS exception: " + e, e);
			}
			catch (CertificateEncodingException e)
			{
				throw new TspException("problem processing certificate: " + e, e);
			}
			catch (SecurityUtilityException e)
			{
				throw new TspException("cannot find algorithm: " + e.Message, e);
			}
		}
コード例 #19
0
		/**
		* Checks if an attribute certificate is revoked.
		* 
		* @param attrCert Attribute certificate to check if it is revoked.
		* @param paramsPKIX PKIX parameters.
		* @param issuerCert The issuer certificate of the attribute certificate
		*            <code>attrCert</code>.
		* @param validDate The date when the certificate revocation status should
		*            be checked.
		* @param certPathCerts The certificates of the certification path to be
		*            checked.
		* 
		* @throws CertPathValidatorException if the certificate is revoked or the
		*             status cannot be checked or some error occurs.
		*/
		internal static void CheckCrls(
			IX509AttributeCertificate	attrCert,
			PkixParameters				paramsPKIX,
			X509Certificate				issuerCert,
			DateTime					validDate,
			IList						certPathCerts)
		{
			if (paramsPKIX.IsRevocationEnabled)
			{
				// check if revocation is available
				if (attrCert.GetExtensionValue(X509Extensions.NoRevAvail) == null)
				{
					CrlDistPoint crldp = null;
					try
					{
						crldp = CrlDistPoint.GetInstance(
							PkixCertPathValidatorUtilities.GetExtensionValue(
								attrCert, X509Extensions.CrlDistributionPoints));
					}
					catch (Exception e)
					{
						throw new PkixCertPathValidatorException(
							"CRL distribution point extension could not be read.", e);
					}
					try
					{
						PkixCertPathValidatorUtilities
							.AddAdditionalStoresFromCrlDistributionPoint(crldp, paramsPKIX);
					}
					catch (Exception e)
					{
						throw new PkixCertPathValidatorException(
							"No additional CRL locations could be decoded from CRL distribution point extension.", e);
					}
					CertStatus certStatus = new CertStatus();
					ReasonsMask reasonsMask = new ReasonsMask();

					Exception lastException = null;
					bool validCrlFound = false;
					// for each distribution point
					if (crldp != null)
					{
						DistributionPoint[] dps = null;
						try
						{
							dps = crldp.GetDistributionPoints();
						}
						catch (Exception e)
						{
							throw new PkixCertPathValidatorException(
								"Distribution points could not be read.", e);
						}
						try
						{
							for (int i = 0; i < dps.Length
								&& certStatus.Status == CertStatus.Unrevoked
								&& !reasonsMask.IsAllReasons; i++)
							{
								PkixParameters paramsPKIXClone = (PkixParameters) paramsPKIX
									.Clone();
								CheckCrl(dps[i], attrCert, paramsPKIXClone,
									validDate, issuerCert, certStatus, reasonsMask,
									certPathCerts);
								validCrlFound = true;
							}
						}
						catch (Exception e)
						{
							lastException = new Exception(
								"No valid CRL for distribution point found.", e);
						}
					}

					/*
					* If the revocation status has not been determined, repeat the
					* process above with any available CRLs not specified in a
					* distribution point but issued by the certificate issuer.
					*/

					if (certStatus.Status == CertStatus.Unrevoked
						&& !reasonsMask.IsAllReasons)
					{
						try
						{
							/*
							* assume a DP with both the reasons and the cRLIssuer
							* fields omitted and a distribution point name of the
							* certificate issuer.
							*/
							Asn1Object issuer = null;
							try
							{
								issuer = new Asn1InputStream(
									attrCert.Issuer.GetPrincipals()[0].GetEncoded()).ReadObject();
							}
							catch (Exception e)
							{
								throw new Exception(
									"Issuer from certificate for CRL could not be reencoded.",
									e);
							}
							DistributionPoint dp = new DistributionPoint(
								new DistributionPointName(0, new GeneralNames(
									new GeneralName(GeneralName.DirectoryName, issuer))), null, null);
							PkixParameters paramsPKIXClone = (PkixParameters) paramsPKIX.Clone();
							CheckCrl(dp, attrCert, paramsPKIXClone, validDate,
								issuerCert, certStatus, reasonsMask, certPathCerts);
							validCrlFound = true;
						}
						catch (Exception e)
						{
							lastException = new Exception(
								"No valid CRL for distribution point found.", e);
						}
					}

					if (!validCrlFound)
					{
						throw new PkixCertPathValidatorException(
							"No valid CRL found.", lastException);
					}
					if (certStatus.Status != CertStatus.Unrevoked)
					{
						// TODO This format is forced by the NistCertPath tests
						string formattedDate = certStatus.RevocationDate.Value.ToString(
                            "G", new CultureInfo("en-us"));
						string message = "Attribute certificate revocation after "
							+ formattedDate;
						message += ", reason: "
							+ Rfc3280CertPathUtilities.CrlReasons[certStatus.Status];
						throw new PkixCertPathValidatorException(message);
					}
					if (!reasonsMask.IsAllReasons
						&& certStatus.Status == CertStatus.Unrevoked)
					{
						certStatus.Status = CertStatus.Undetermined;
					}
					if (certStatus.Status == CertStatus.Undetermined)
					{
						throw new PkixCertPathValidatorException(
							"Attribute certificate status could not be determined.");
					}

				}
				else
				{
					if (attrCert.GetExtensionValue(X509Extensions.CrlDistributionPoints) != null
						|| attrCert.GetExtensionValue(X509Extensions.AuthorityInfoAccess) != null)
					{
						throw new PkixCertPathValidatorException(
							"No rev avail extension is set, but also an AC revocation pointer.");
					}
				}
			}
		}
コード例 #20
0
		/**
		* Add a key agreement based recipient.
		*
		* @param agreementAlgorithm key agreement algorithm to use.
		* @param senderPrivateKey private key to initialise sender side of agreement with.
		* @param senderPublicKey sender public key to include with message.
		* @param recipientCert recipient's public key certificate.
		* @param cekWrapAlgorithm OID for key wrapping algorithm to use.
		* @exception SecurityUtilityException if the algorithm requested cannot be found
		* @exception InvalidKeyException if the keys are inappropriate for the algorithm specified
		*/
		public void AddKeyAgreementRecipient(
			string					agreementAlgorithm,
			AsymmetricKeyParameter	senderPrivateKey,
			AsymmetricKeyParameter	senderPublicKey,
			X509Certificate			recipientCert,
			string					cekWrapAlgorithm)
		{
            IList recipientCerts = Platform.CreateArrayList(1);
			recipientCerts.Add(recipientCert);

			AddKeyAgreementRecipients(agreementAlgorithm, senderPrivateKey, senderPublicKey,
				recipientCerts, cekWrapAlgorithm);
		}
コード例 #21
0
		/**
		 * add a recipient.
		 *
		 * @param cert recipient's public key certificate
		 * @exception ArgumentException if there is a problem with the certificate
		 */
		public void AddKeyTransRecipient(
			X509Certificate cert)
		{
			KeyTransRecipientInfoGenerator ktrig = new KeyTransRecipientInfoGenerator();
			ktrig.RecipientCert = cert;

			recipientInfoGenerators.Add(ktrig);
		}
コード例 #22
0
		/**
		* Checks a distribution point for revocation information for the
		* certificate <code>cert</code>.
		*
		* @param dp                 The distribution point to consider.
		* @param paramsPKIX         PKIX parameters.
		* @param cert               Certificate to check if it is revoked.
		* @param validDate          The date when the certificate revocation status should be
		*                           checked.
		* @param defaultCRLSignCert The issuer certificate of the certificate <code>cert</code>.
		* @param defaultCRLSignKey  The public key of the issuer certificate
		*                           <code>defaultCRLSignCert</code>.
		* @param certStatus         The current certificate revocation status.
		* @param reasonMask         The reasons mask which is already checked.
		* @param certPathCerts      The certificates of the certification path.
		* @throws AnnotatedException if the certificate is revoked or the status cannot be checked
		*                            or some error occurs.
		*/
		private static void CheckCrl(
			DistributionPoint dp,
			PkixParameters paramsPKIX,
			X509Certificate cert,
			DateTime validDate,
			X509Certificate defaultCRLSignCert,
			AsymmetricKeyParameter defaultCRLSignKey,
			CertStatus certStatus,
			ReasonsMask reasonMask,
			IList certPathCerts)
			//throws AnnotatedException
		{
			DateTime currentDate = DateTime.UtcNow;

			if (validDate.Ticks > currentDate.Ticks)
			{
				throw new Exception("Validation time is in future.");
			}

			// (a)
			/*
			 * We always get timely valid CRLs, so there is no step (a) (1).
			 * "locally cached" CRLs are assumed to be in getStore(), additional
			 * CRLs must be enabled in the ExtendedPKIXParameters and are in
			 * getAdditionalStore()
			 */

			ISet crls = PkixCertPathValidatorUtilities.GetCompleteCrls(dp, cert, currentDate, paramsPKIX);
			bool validCrlFound = false;
			Exception lastException = null;

			IEnumerator crl_iter = crls.GetEnumerator();

			while (crl_iter.MoveNext() && certStatus.Status == CertStatus.Unrevoked && !reasonMask.IsAllReasons)
			{
				try
				{
					X509Crl crl = (X509Crl)crl_iter.Current;

					// (d)
					ReasonsMask interimReasonsMask = Rfc3280CertPathUtilities.ProcessCrlD(crl, dp);

					// (e)
					/*
					 * The reasons mask is updated at the end, so only valid CRLs
					 * can update it. If this CRL does not contain new reasons it
					 * must be ignored.
					 */
					if (!interimReasonsMask.HasNewReasons(reasonMask))
					{
						continue;
					}

					// (f)
					ISet keys = Rfc3280CertPathUtilities.ProcessCrlF(crl, cert, defaultCRLSignCert, defaultCRLSignKey,
						paramsPKIX, certPathCerts);
					// (g)
					AsymmetricKeyParameter key = Rfc3280CertPathUtilities.ProcessCrlG(crl, keys);

					X509Crl deltaCRL = null;

					if (paramsPKIX.IsUseDeltasEnabled)
					{
						// get delta CRLs
						ISet deltaCRLs = PkixCertPathValidatorUtilities.GetDeltaCrls(currentDate, paramsPKIX, crl);
						// we only want one valid delta CRL
						// (h)
						deltaCRL = Rfc3280CertPathUtilities.ProcessCrlH(deltaCRLs, key);
					}

					/*
					 * CRL must be be valid at the current time, not the validation
					 * time. If a certificate is revoked with reason keyCompromise,
					 * cACompromise, it can be used for forgery, also for the past.
					 * This reason may not be contained in older CRLs.
					 */

					/*
					 * in the chain model signatures stay valid also after the
					 * certificate has been expired, so they do not have to be in
					 * the CRL validity time
					 */

					if (paramsPKIX.ValidityModel != PkixParameters.ChainValidityModel)
					{
						/*
						 * if a certificate has expired, but was revoked, it is not
						 * more in the CRL, so it would be regarded as valid if the
						 * first check is not done
						 */
						if (cert.NotAfter.Ticks < crl.ThisUpdate.Ticks)
						{
							throw new Exception("No valid CRL for current time found.");
						}
					}

					Rfc3280CertPathUtilities.ProcessCrlB1(dp, cert, crl);

					// (b) (2)
					Rfc3280CertPathUtilities.ProcessCrlB2(dp, cert, crl);

					// (c)
					Rfc3280CertPathUtilities.ProcessCrlC(deltaCRL, crl, paramsPKIX);

					// (i)
					Rfc3280CertPathUtilities.ProcessCrlI(validDate, deltaCRL, cert, certStatus, paramsPKIX);

					// (j)
					Rfc3280CertPathUtilities.ProcessCrlJ(validDate, crl, cert, certStatus);

					// (k)
					if (certStatus.Status == CrlReason.RemoveFromCrl)
					{
						certStatus.Status = CertStatus.Unrevoked;
					}

					// update reasons mask
					reasonMask.AddReasons(interimReasonsMask);

					ISet criticalExtensions = crl.GetCriticalExtensionOids();

					if (criticalExtensions != null)
					{
						criticalExtensions = new HashSet(criticalExtensions);
						criticalExtensions.Remove(X509Extensions.IssuingDistributionPoint.Id);
						criticalExtensions.Remove(X509Extensions.DeltaCrlIndicator.Id);

						if (!criticalExtensions.IsEmpty)
							throw new Exception("CRL contains unsupported critical extensions.");
					}

					if (deltaCRL != null)
					{
						criticalExtensions = deltaCRL.GetCriticalExtensionOids();
						if (criticalExtensions != null)
						{
							criticalExtensions = new HashSet(criticalExtensions);
							criticalExtensions.Remove(X509Extensions.IssuingDistributionPoint.Id);
							criticalExtensions.Remove(X509Extensions.DeltaCrlIndicator.Id);

							if (!criticalExtensions.IsEmpty)
								throw new Exception("Delta CRL contains unsupported critical extension.");
						}
					}

					validCrlFound = true;
				}
				catch (Exception e)
				{
					lastException = e;
				}
			}
			if (!validCrlFound)
			{
				throw lastException;
			}
		}
コード例 #23
0
		/// <summary>
		/// Creates an instance of <code>TrustAnchor</code> where the most-trusted
		/// CA is specified as a distinguished name and public key. Name constraints
		/// are an optional parameter, and are intended to be used as additional
		/// constraints when validating an X.509 certification path.
		/// <br/>
		/// The name constraints are specified as a byte array. This byte array
		/// contains the DER encoded form of the name constraints, as they would
		/// appear in the NameConstraints structure defined in RFC 2459 and X.509.
		/// </summary>
		/// <param name="caName">the X.500 distinguished name of the most-trusted CA in RFC
		/// 2253 string format</param>
		/// <param name="pubKey">the public key of the most-trusted CA</param>
		/// <param name="nameConstraints">a byte array containing the ASN.1 DER encoding of a
		/// NameConstraints extension to be used for checking name
		/// constraints. Only the value of the extension is included, not 
		/// the OID or criticality flag. Specify null to omit the 
		/// parameter.</param>
		/// throws NullPointerException, IllegalArgumentException
		public TrustAnchor(
			string					caName,
			AsymmetricKeyParameter	pubKey,
			byte[]					nameConstraints)
		{
			if (caName == null)
				throw new ArgumentNullException("caName");
			if (pubKey == null)
				throw new ArgumentNullException("pubKey");
			if (caName.Length == 0)
				throw new ArgumentException("caName can not be an empty string");

			this.caPrincipal = new X509Name(caName);
			this.pubKey = pubKey;
			this.caName = caName;
			this.trustedCert = null;
			setNameConstraints(nameConstraints);
		}
コード例 #24
0
		internal static ISet[] ProcessCrlA1ii(
			DateTime		currentDate,
			PkixParameters	paramsPKIX,
			X509Certificate	cert,
			X509Crl			crl)
		{
			ISet deltaSet = new HashSet();
			X509CrlStoreSelector crlselect = new X509CrlStoreSelector();
			crlselect.CertificateChecking = cert;

			try
			{
				IList issuer = Platform.CreateArrayList();
				issuer.Add(crl.IssuerDN);
				crlselect.Issuers = issuer;
			}
			catch (IOException e)
			{
				throw new Exception("Cannot extract issuer from CRL." + e, e);
			}

			crlselect.CompleteCrlEnabled = true;
			ISet completeSet = CrlUtilities.FindCrls(crlselect, paramsPKIX, currentDate);

			if (paramsPKIX.IsUseDeltasEnabled)
			{
				// get delta CRL(s)
				try
				{
					deltaSet.AddAll(PkixCertPathValidatorUtilities.GetDeltaCrls(currentDate, paramsPKIX, crl));
				}
				catch (Exception e)
				{
					throw new Exception("Exception obtaining delta CRLs.", e);
				}
			}

			return new ISet[]{ completeSet, deltaSet };
		}
コード例 #25
0
		internal static ISet ProcessCrlA1i(
			DateTime		currentDate,
			PkixParameters	paramsPKIX,
			X509Certificate	cert,
			X509Crl			crl)
		{
			ISet deltaSet = new HashSet();
			if (paramsPKIX.IsUseDeltasEnabled)
			{
				CrlDistPoint freshestCRL = null;
				try
				{
					freshestCRL = CrlDistPoint.GetInstance(
						PkixCertPathValidatorUtilities.GetExtensionValue(cert, X509Extensions.FreshestCrl));
				}
				catch (Exception e)
				{
					throw new Exception("Freshest CRL extension could not be decoded from certificate.", e);
				}

				if (freshestCRL == null)
				{
					try
					{
						freshestCRL = CrlDistPoint.GetInstance(PkixCertPathValidatorUtilities.GetExtensionValue(crl, X509Extensions.FreshestCrl));
					}
					catch (Exception e)
					{
						throw new Exception("Freshest CRL extension could not be decoded from CRL.", e);
					}
				}
				if (freshestCRL != null)
				{
					try
					{
						PkixCertPathValidatorUtilities.AddAdditionalStoresFromCrlDistributionPoint(freshestCRL, paramsPKIX);
					}
					catch (Exception e)
					{
						throw new Exception(
							"No new delta CRL locations could be added from Freshest CRL extension.", e);
					}
					// get delta CRL(s)
					try
					{
						deltaSet.AddAll(PkixCertPathValidatorUtilities.GetDeltaCrls(currentDate, paramsPKIX, crl));
					}
					catch (Exception e)
					{
						throw new Exception("Exception obtaining delta CRLs.", e);
					}
				}
			}
			return deltaSet;
		}
コード例 #26
0
		public OcspReq Generate(
			string					signingAlgorithm,
			AsymmetricKeyParameter	privateKey,
			X509Certificate[]		chain)
		{
			return Generate(signingAlgorithm, privateKey, chain, null);
		}
コード例 #27
0
		public bool Match(
//			Certificate cert)
			X509Certificate x509Cert)
		{
//			if (!(cert is X509Certificate))
//			{
//				return false;
//			}
//
//			X509Certificate x509Cert = (X509Certificate)cert;

			try
			{
				if (holder.BaseCertificateID != null)
				{
					return holder.BaseCertificateID.Serial.Value.Equals(x509Cert.SerialNumber)
						&& MatchesDN(PrincipalUtilities.GetIssuerX509Principal(x509Cert), holder.BaseCertificateID.Issuer);
				}

				if (holder.EntityName != null)
				{
					if (MatchesDN(PrincipalUtilities.GetSubjectX509Principal(x509Cert), holder.EntityName))
					{
						return true;
					}
				}

				if (holder.ObjectDigestInfo != null)
				{
					IDigest md = null;
					try
					{
						md = DigestUtilities.GetDigest(DigestAlgorithm);
					}
					catch (Exception)
					{
						return false;
					}

					switch (DigestedObjectType)
					{
						case ObjectDigestInfo.PublicKey:
						{
							// TODO: DSA Dss-parms

							//byte[] b = x509Cert.GetPublicKey().getEncoded();
							// TODO Is this the right way to encode?
							byte[] b = SubjectPublicKeyInfoFactory.CreateSubjectPublicKeyInfo(
								x509Cert.GetPublicKey()).GetEncoded();
							md.BlockUpdate(b, 0, b.Length);
							break;
						}

						case ObjectDigestInfo.PublicKeyCert:
						{
							byte[] b = x509Cert.GetEncoded();
							md.BlockUpdate(b, 0, b.Length);
							break;
						}

						// TODO Default handler?
					}

					// TODO Shouldn't this be the other way around?
					if (!Arrays.AreEqual(DigestUtilities.DoFinal(md), GetObjectDigest()))
					{
						return false;
					}
				}
			}
			catch (CertificateEncodingException)
			{
				return false;
			}

			return false;
		}
コード例 #28
0
		internal static int WrapupCertA(
			int				explicitPolicy,
			X509Certificate	cert)
		{
			//
			// (a)
			//
			if (!PkixCertPathValidatorUtilities.IsSelfIssued(cert) && (explicitPolicy != 0))
			{
				explicitPolicy--;
			}
			return explicitPolicy;
		}
コード例 #29
0
		public X509Certificate[] GetCerts()
		{
			IList certs = GetCertList();
            X509Certificate[] result = new X509Certificate[certs.Count];
            for (int i = 0; i < certs.Count; ++i)
            {
                result[i] = (X509Certificate)certs[i];
            }
            return result;
		}
コード例 #30
0
		/**
		 * Checks a certificate if it is revoked.
		 *
		 * @param paramsPKIX       PKIX parameters.
		 * @param cert             Certificate to check if it is revoked.
		 * @param validDate        The date when the certificate revocation status should be
		 *                         checked.
		 * @param sign             The issuer certificate of the certificate <code>cert</code>.
		 * @param workingPublicKey The public key of the issuer certificate <code>sign</code>.
		 * @param certPathCerts    The certificates of the certification path.
		 * @throws AnnotatedException if the certificate is revoked or the status cannot be checked
		 *                            or some error occurs.
		 */
		protected static void CheckCrls(
			PkixParameters			paramsPKIX,
			X509Certificate			cert,
			DateTime				validDate,
			X509Certificate			sign,
			AsymmetricKeyParameter	workingPublicKey,
			IList					certPathCerts)
		{
			Exception lastException = null;
			CrlDistPoint crldp = null;

			try
			{
				crldp = CrlDistPoint.GetInstance(PkixCertPathValidatorUtilities.GetExtensionValue(cert, X509Extensions.CrlDistributionPoints));
			}
			catch (Exception e)
			{
				throw new Exception("CRL distribution point extension could not be read.", e);
			}

			try
			{
				PkixCertPathValidatorUtilities.AddAdditionalStoresFromCrlDistributionPoint(crldp, paramsPKIX);
			}
			catch (Exception e)
			{
				throw new Exception(
					"No additional CRL locations could be decoded from CRL distribution point extension.", e);
			}
			CertStatus certStatus = new CertStatus();
			ReasonsMask reasonsMask = new ReasonsMask();

			bool validCrlFound = false;

			// for each distribution point
			if (crldp != null)
			{
				DistributionPoint[] dps = null;
				try
				{
					dps = crldp.GetDistributionPoints();
				}
				catch (Exception e)
				{
					throw new Exception("Distribution points could not be read.", e);
				}
				if (dps != null)
				{
					for (int i = 0; i < dps.Length && certStatus.Status == CertStatus.Unrevoked && !reasonsMask.IsAllReasons; i++)
					{
						PkixParameters paramsPKIXClone = (PkixParameters)paramsPKIX.Clone();
						try
						{
							CheckCrl(dps[i], paramsPKIXClone, cert, validDate, sign, workingPublicKey, certStatus, reasonsMask, certPathCerts);
							validCrlFound = true;
						}
						catch (Exception e)
						{
							lastException = e;
						}
					}
				}
			}

			/*
			 * If the revocation status has not been determined, repeat the process
			 * above with any available CRLs not specified in a distribution point
			 * but issued by the certificate issuer.
			 */

			if (certStatus.Status == CertStatus.Unrevoked && !reasonsMask.IsAllReasons)
			{
				try
				{
					/*
					 * assume a DP with both the reasons and the cRLIssuer fields
					 * omitted and a distribution point name of the certificate
					 * issuer.
					 */
					Asn1Object issuer = null;
					try
					{
						issuer = new Asn1InputStream(cert.IssuerDN.GetEncoded()).ReadObject();
					}
					catch (Exception e)
					{
						throw new Exception("Issuer from certificate for CRL could not be reencoded.", e);
					}
					DistributionPoint dp = new DistributionPoint(new DistributionPointName(0, new GeneralNames(
						new GeneralName(GeneralName.DirectoryName, issuer))), null, null);
					PkixParameters paramsPKIXClone = (PkixParameters)paramsPKIX.Clone();

					CheckCrl(dp, paramsPKIXClone, cert, validDate, sign, workingPublicKey, certStatus, reasonsMask,
						certPathCerts);

					validCrlFound = true;
				}
				catch (Exception e)
				{
					lastException = e;
				}
			}

			if (!validCrlFound)
			{
				throw lastException;
			}
			if (certStatus.Status != CertStatus.Unrevoked)
			{
				// TODO This format is forced by the NistCertPath tests
				string formattedDate = certStatus.RevocationDate.Value.ToString(
					"G", new CultureInfo("en-us"));
				string message = "Certificate revocation after " + formattedDate;
				message += ", reason: " + CrlReasons[certStatus.Status];
				throw new Exception(message);
			}

			if (!reasonsMask.IsAllReasons && certStatus.Status == CertStatus.Unrevoked)
			{
				certStatus.Status = CertStatus.Undetermined;
			}

			if (certStatus.Status == CertStatus.Undetermined)
			{
				throw new Exception("Certificate status could not be determined.");
			}
		}