diff --git a/Crypto/src/asn1/cmp/CAKeyUpdAnnContent.cs b/Crypto/src/asn1/cmp/CAKeyUpdAnnContent.cs
new file mode 100644
index 000000000..3cdb128a6
--- /dev/null
+++ b/Crypto/src/asn1/cmp/CAKeyUpdAnnContent.cs
@@ -0,0 +1,60 @@
+using System;
+
+namespace Org.BouncyCastle.Asn1.Cmp
+{
+ public class CAKeyUpdAnnContent
+ : Asn1Encodable
+ {
+ private readonly CmpCertificate oldWithNew;
+ private readonly CmpCertificate newWithOld;
+ private readonly CmpCertificate newWithNew;
+
+ private CAKeyUpdAnnContent(Asn1Sequence seq)
+ {
+ oldWithNew = CmpCertificate.GetInstance(seq[0]);
+ newWithOld = CmpCertificate.GetInstance(seq[1]);
+ newWithNew = CmpCertificate.GetInstance(seq[2]);
+ }
+
+ public static CAKeyUpdAnnContent GetInstance(object obj)
+ {
+ if (obj is CAKeyUpdAnnContent)
+ return (CAKeyUpdAnnContent)obj;
+
+ if (obj is Asn1Sequence)
+ return new CAKeyUpdAnnContent((Asn1Sequence)obj);
+
+ throw new ArgumentException("Invalid object: " + obj.GetType().Name, "obj");
+ }
+
+ public virtual CmpCertificate OldWithNew
+ {
+ get { return oldWithNew; }
+ }
+
+ public virtual CmpCertificate NewWithOld
+ {
+ get { return newWithOld; }
+ }
+
+ public virtual CmpCertificate NewWithNew
+ {
+ get { return newWithNew; }
+ }
+
+ /**
+ * <pre>
+ * CAKeyUpdAnnContent ::= SEQUENCE {
+ * oldWithNew CmpCertificate, -- old pub signed with new priv
+ * newWithOld CmpCertificate, -- new pub signed with old priv
+ * newWithNew CmpCertificate -- new pub signed with new priv
+ * }
+ * </pre>
+ * @return a basic ASN.1 object representation.
+ */
+ public override Asn1Object ToAsn1Object()
+ {
+ return new DerSequence(oldWithNew, newWithOld, newWithNew);
+ }
+ }
+}
diff --git a/Crypto/src/asn1/cmp/CertConfirmContent.cs b/Crypto/src/asn1/cmp/CertConfirmContent.cs
new file mode 100644
index 000000000..f4016d8d8
--- /dev/null
+++ b/Crypto/src/asn1/cmp/CertConfirmContent.cs
@@ -0,0 +1,47 @@
+using System;
+
+namespace Org.BouncyCastle.Asn1.Cmp
+{
+ public class CertConfirmContent
+ : Asn1Encodable
+ {
+ private readonly Asn1Sequence content;
+
+ private CertConfirmContent(Asn1Sequence seq)
+ {
+ content = seq;
+ }
+
+ public static CertConfirmContent GetInstance(object obj)
+ {
+ if (obj is CertConfirmContent)
+ return (CertConfirmContent)obj;
+
+ if (obj is Asn1Sequence)
+ return new CertConfirmContent((Asn1Sequence)obj);
+
+ throw new ArgumentException("Invalid object: " + obj.GetType().Name, "obj");
+ }
+
+ public virtual CertStatus[] ToCertStatusArray()
+ {
+ CertStatus[] result = new CertStatus[content.Count];
+ for (int i = 0; i != result.Length; i++)
+ {
+ result[i] = CertStatus.GetInstance(content[i]);
+ }
+ return result;
+ }
+
+ /**
+ * <pre>
+ * CertConfirmContent ::= SEQUENCE OF CertStatus
+ * </pre>
+ * @return a basic ASN.1 object representation.
+ */
+ public override Asn1Object ToAsn1Object()
+ {
+ return content;
+ }
+ }
+}
diff --git a/Crypto/src/asn1/cmp/CertOrEncCert.cs b/Crypto/src/asn1/cmp/CertOrEncCert.cs
new file mode 100644
index 000000000..4c049c180
--- /dev/null
+++ b/Crypto/src/asn1/cmp/CertOrEncCert.cs
@@ -0,0 +1,85 @@
+using System;
+
+using Org.BouncyCastle.Asn1.Crmf;
+
+namespace Org.BouncyCastle.Asn1.Cmp
+{
+ public class CertOrEncCert
+ : Asn1Encodable, IAsn1Choice
+ {
+ private readonly CmpCertificate certificate;
+ private readonly EncryptedValue encryptedCert;
+
+ private CertOrEncCert(Asn1TaggedObject tagged)
+ {
+ if (tagged.TagNo == 0)
+ {
+ certificate = CmpCertificate.GetInstance(tagged.GetObject());
+ }
+ else if (tagged.TagNo == 1)
+ {
+ encryptedCert = EncryptedValue.GetInstance(tagged.GetObject());
+ }
+ else
+ {
+ throw new ArgumentException("unknown tag: " + tagged.TagNo, "tagged");
+ }
+ }
+
+ public static CertOrEncCert GetInstance(object obj)
+ {
+ if (obj is CertOrEncCert)
+ return (CertOrEncCert)obj;
+
+ if (obj is Asn1TaggedObject)
+ return new CertOrEncCert((Asn1TaggedObject)obj);
+
+ throw new ArgumentException("Invalid object: " + obj.GetType().Name, "obj");
+ }
+
+ public CertOrEncCert(CmpCertificate certificate)
+ {
+ if (certificate == null)
+ throw new ArgumentNullException("certificate");
+
+ this.certificate = certificate;
+ }
+
+ public CertOrEncCert(EncryptedValue encryptedCert)
+ {
+ if (encryptedCert == null)
+ throw new ArgumentNullException("encryptedCert");
+
+ this.encryptedCert = encryptedCert;
+ }
+
+ public virtual CmpCertificate Certificate
+ {
+ get { return certificate; }
+ }
+
+ public virtual EncryptedValue EncryptedCert
+ {
+ get { return encryptedCert; }
+ }
+
+ /**
+ * <pre>
+ * CertOrEncCert ::= CHOICE {
+ * certificate [0] CMPCertificate,
+ * encryptedCert [1] EncryptedValue
+ * }
+ * </pre>
+ * @return a basic ASN.1 object representation.
+ */
+ public override Asn1Object ToAsn1Object()
+ {
+ if (certificate != null)
+ {
+ return new DerTaggedObject(true, 0, certificate);
+ }
+
+ return new DerTaggedObject(true, 1, encryptedCert);
+ }
+ }
+}
diff --git a/Crypto/src/asn1/cmp/CertRepMessage.cs b/Crypto/src/asn1/cmp/CertRepMessage.cs
new file mode 100644
index 000000000..c22b079c8
--- /dev/null
+++ b/Crypto/src/asn1/cmp/CertRepMessage.cs
@@ -0,0 +1,94 @@
+using System;
+
+namespace Org.BouncyCastle.Asn1.Cmp
+{
+ public class CertRepMessage
+ : Asn1Encodable
+ {
+ private readonly Asn1Sequence caPubs;
+ private readonly Asn1Sequence response;
+
+ private CertRepMessage(Asn1Sequence seq)
+ {
+ int index = 0;
+
+ if (seq.Count > 1)
+ {
+ caPubs = Asn1Sequence.GetInstance((Asn1TaggedObject)seq[index++], true);
+ }
+
+ response = Asn1Sequence.GetInstance(seq[index]);
+ }
+
+ public static CertRepMessage GetInstance(object obj)
+ {
+ if (obj is CertRepMessage)
+ return (CertRepMessage)obj;
+
+ if (obj is Asn1Sequence)
+ return new CertRepMessage((Asn1Sequence)obj);
+
+ throw new ArgumentException("Invalid object: " + obj.GetType().Name, "obj");
+ }
+
+ public CertRepMessage(CmpCertificate[] caPubs, CertResponse[] response)
+ {
+ if (response == null)
+ throw new ArgumentNullException("response");
+
+ if (caPubs != null)
+ {
+ this.caPubs = new DerSequence(caPubs);
+ }
+
+ this.response = new DerSequence(response);
+ }
+
+ public virtual CmpCertificate[] GetCAPubs()
+ {
+ if (caPubs == null)
+ return null;
+
+ CmpCertificate[] results = new CmpCertificate[caPubs.Count];
+ for (int i = 0; i != results.Length; ++i)
+ {
+ results[i] = CmpCertificate.GetInstance(caPubs[i]);
+ }
+ return results;
+ }
+
+ public virtual CertResponse[] GetResponse()
+ {
+ CertResponse[] results = new CertResponse[response.Count];
+ for (int i = 0; i != results.Length; ++i)
+ {
+ results[i] = CertResponse.GetInstance(response[i]);
+ }
+ return results;
+ }
+
+ /**
+ * <pre>
+ * CertRepMessage ::= SEQUENCE {
+ * caPubs [1] SEQUENCE SIZE (1..MAX) OF CMPCertificate
+ * OPTIONAL,
+ * response SEQUENCE OF CertResponse
+ * }
+ * </pre>
+ * @return a basic ASN.1 object representation.
+ */
+ public override Asn1Object ToAsn1Object()
+ {
+ Asn1EncodableVector v = new Asn1EncodableVector();
+
+ if (caPubs != null)
+ {
+ v.Add(new DerTaggedObject(true, 1, caPubs));
+ }
+
+ v.Add(response);
+
+ return new DerSequence(v);
+ }
+ }
+}
diff --git a/Crypto/src/asn1/cmp/CertResponse.cs b/Crypto/src/asn1/cmp/CertResponse.cs
new file mode 100644
index 000000000..246b8ce70
--- /dev/null
+++ b/Crypto/src/asn1/cmp/CertResponse.cs
@@ -0,0 +1,115 @@
+using System;
+
+namespace Org.BouncyCastle.Asn1.Cmp
+{
+ public class CertResponse
+ : Asn1Encodable
+ {
+ private readonly DerInteger certReqId;
+ private readonly PkiStatusInfo status;
+ private readonly CertifiedKeyPair certifiedKeyPair;
+ private readonly Asn1OctetString rspInfo;
+
+ private CertResponse(Asn1Sequence seq)
+ {
+ certReqId = DerInteger.GetInstance(seq[0]);
+ status = PkiStatusInfo.GetInstance(seq[1]);
+
+ if (seq.Count >= 3)
+ {
+ if (seq.Count == 3)
+ {
+ Asn1Encodable o = seq[2];
+ if (o is Asn1OctetString)
+ {
+ rspInfo = Asn1OctetString.GetInstance(o);
+ }
+ else
+ {
+ certifiedKeyPair = CertifiedKeyPair.GetInstance(o);
+ }
+ }
+ else
+ {
+ certifiedKeyPair = CertifiedKeyPair.GetInstance(seq[2]);
+ rspInfo = Asn1OctetString.GetInstance(seq[3]);
+ }
+ }
+ }
+
+ public static CertResponse GetInstance(object obj)
+ {
+ if (obj is CertResponse)
+ return (CertResponse)obj;
+
+ if (obj is Asn1Sequence)
+ return new CertResponse((Asn1Sequence)obj);
+
+ throw new ArgumentException("Invalid object: " + obj.GetType().Name, "obj");
+ }
+
+ public CertResponse(
+ DerInteger certReqId,
+ PkiStatusInfo status)
+ : this(certReqId, status, null, null)
+ {
+ }
+
+ public CertResponse(
+ DerInteger certReqId,
+ PkiStatusInfo status,
+ CertifiedKeyPair certifiedKeyPair,
+ Asn1OctetString rspInfo)
+ {
+ if (certReqId == null)
+ throw new ArgumentNullException("certReqId");
+
+ if (status == null)
+ throw new ArgumentNullException("status");
+
+ this.certReqId = certReqId;
+ this.status = status;
+ this.certifiedKeyPair = certifiedKeyPair;
+ this.rspInfo = rspInfo;
+ }
+
+ public virtual DerInteger CertReqID
+ {
+ get { return certReqId; }
+ }
+
+ public virtual PkiStatusInfo Status
+ {
+ get { return status; }
+ }
+
+ public virtual CertifiedKeyPair CertifiedKeyPair
+ {
+ get { return certifiedKeyPair; }
+ }
+
+ /**
+ * <pre>
+ * CertResponse ::= SEQUENCE {
+ * certReqId INTEGER,
+ * -- to match this response with corresponding request (a value
+ * -- of -1 is to be used if certReqId is not specified in the
+ * -- corresponding request)
+ * status PKIStatusInfo,
+ * certifiedKeyPair CertifiedKeyPair OPTIONAL,
+ * rspInfo OCTET STRING OPTIONAL
+ * -- analogous to the id-regInfo-utf8Pairs string defined
+ * -- for regInfo in CertReqMsg [CRMF]
+ * }
+ * </pre>
+ * @return a basic ASN.1 object representation.
+ */
+ public override Asn1Object ToAsn1Object()
+ {
+ Asn1EncodableVector v = new Asn1EncodableVector(certReqId, status);
+ v.AddOptional(certifiedKeyPair);
+ v.AddOptional(rspInfo);
+ return new DerSequence(v);
+ }
+ }
+}
diff --git a/Crypto/src/asn1/cmp/CertStatus.cs b/Crypto/src/asn1/cmp/CertStatus.cs
new file mode 100644
index 000000000..52d5ac504
--- /dev/null
+++ b/Crypto/src/asn1/cmp/CertStatus.cs
@@ -0,0 +1,84 @@
+using System;
+
+using Org.BouncyCastle.Math;
+
+namespace Org.BouncyCastle.Asn1.Cmp
+{
+ public class CertStatus
+ : Asn1Encodable
+ {
+ private readonly Asn1OctetString certHash;
+ private readonly DerInteger certReqId;
+ private readonly PkiStatusInfo statusInfo;
+
+ private CertStatus(Asn1Sequence seq)
+ {
+ certHash = Asn1OctetString.GetInstance(seq[0]);
+ certReqId = DerInteger.GetInstance(seq[1]);
+
+ if (seq.Count > 2)
+ {
+ statusInfo = PkiStatusInfo.GetInstance(seq[2]);
+ }
+ }
+
+ public CertStatus(byte[] certHash, BigInteger certReqId)
+ {
+ this.certHash = new DerOctetString(certHash);
+ this.certReqId = new DerInteger(certReqId);
+ }
+
+ public CertStatus(byte[] certHash, BigInteger certReqId, PkiStatusInfo statusInfo)
+ {
+ this.certHash = new DerOctetString(certHash);
+ this.certReqId = new DerInteger(certReqId);
+ this.statusInfo = statusInfo;
+ }
+
+ public static CertStatus GetInstance(object obj)
+ {
+ if (obj is CertStatus)
+ return (CertStatus)obj;
+
+ if (obj is Asn1Sequence)
+ return new CertStatus((Asn1Sequence)obj);
+
+ throw new ArgumentException("Invalid object: " + obj.GetType().Name, "obj");
+ }
+
+ public virtual Asn1OctetString CertHash
+ {
+ get { return certHash; }
+ }
+
+ public virtual DerInteger CertReqID
+ {
+ get { return certReqId; }
+ }
+
+ public virtual PkiStatusInfo StatusInfo
+ {
+ get { return statusInfo; }
+ }
+
+ /**
+ * <pre>
+ * CertStatus ::= SEQUENCE {
+ * certHash OCTET STRING,
+ * -- the hash of the certificate, using the same hash algorithm
+ * -- as is used to create and verify the certificate signature
+ * certReqId INTEGER,
+ * -- to match this confirmation with the corresponding req/rep
+ * statusInfo PKIStatusInfo OPTIONAL
+ * }
+ * </pre>
+ * @return a basic ASN.1 object representation.
+ */
+ public override Asn1Object ToAsn1Object()
+ {
+ Asn1EncodableVector v = new Asn1EncodableVector(certHash, certReqId);
+ v.AddOptional(statusInfo);
+ return new DerSequence(v);
+ }
+ }
+}
diff --git a/Crypto/src/asn1/cmp/CertifiedKeyPair.cs b/Crypto/src/asn1/cmp/CertifiedKeyPair.cs
new file mode 100644
index 000000000..655dde0c5
--- /dev/null
+++ b/Crypto/src/asn1/cmp/CertifiedKeyPair.cs
@@ -0,0 +1,114 @@
+using System;
+
+using Org.BouncyCastle.Asn1.Crmf;
+
+namespace Org.BouncyCastle.Asn1.Cmp
+{
+ public class CertifiedKeyPair
+ : Asn1Encodable
+ {
+ private readonly CertOrEncCert certOrEncCert;
+ private readonly EncryptedValue privateKey;
+ private readonly PkiPublicationInfo publicationInfo;
+
+ private CertifiedKeyPair(Asn1Sequence seq)
+ {
+ certOrEncCert = CertOrEncCert.GetInstance(seq[0]);
+
+ if (seq.Count >= 2)
+ {
+ if (seq.Count == 2)
+ {
+ Asn1TaggedObject tagged = Asn1TaggedObject.GetInstance(seq[1]);
+ if (tagged.TagNo == 0)
+ {
+ privateKey = EncryptedValue.GetInstance(tagged.GetObject());
+ }
+ else
+ {
+ publicationInfo = PkiPublicationInfo.GetInstance(tagged.GetObject());
+ }
+ }
+ else
+ {
+ privateKey = EncryptedValue.GetInstance(Asn1TaggedObject.GetInstance(seq[1]));
+ publicationInfo = PkiPublicationInfo.GetInstance(Asn1TaggedObject.GetInstance(seq[2]));
+ }
+ }
+ }
+
+ public static CertifiedKeyPair GetInstance(object obj)
+ {
+ if (obj is CertifiedKeyPair)
+ return (CertifiedKeyPair)obj;
+
+ if (obj is Asn1Sequence)
+ return new CertifiedKeyPair((Asn1Sequence)obj);
+
+ throw new ArgumentException("Invalid object: " + obj.GetType().Name, "obj");
+ }
+
+ public CertifiedKeyPair(
+ CertOrEncCert certOrEncCert)
+ : this(certOrEncCert, null, null)
+ {
+ }
+
+ public CertifiedKeyPair(
+ CertOrEncCert certOrEncCert,
+ EncryptedValue privateKey,
+ PkiPublicationInfo publicationInfo
+ )
+ {
+ if (certOrEncCert == null)
+ throw new ArgumentNullException("certOrEncCert");
+
+ this.certOrEncCert = certOrEncCert;
+ this.privateKey = privateKey;
+ this.publicationInfo = publicationInfo;
+ }
+
+ public virtual CertOrEncCert CertOrEncCert
+ {
+ get { return certOrEncCert; }
+ }
+
+ public virtual EncryptedValue PrivateKey
+ {
+ get { return privateKey; }
+ }
+
+ public virtual PkiPublicationInfo PublicationInfo
+ {
+ get { return publicationInfo; }
+ }
+
+ /**
+ * <pre>
+ * CertifiedKeyPair ::= SEQUENCE {
+ * certOrEncCert CertOrEncCert,
+ * privateKey [0] EncryptedValue OPTIONAL,
+ * -- see [CRMF] for comment on encoding
+ * publicationInfo [1] PKIPublicationInfo OPTIONAL
+ * }
+ * </pre>
+ * @return a basic ASN.1 object representation.
+ */
+ public override Asn1Object ToAsn1Object()
+ {
+ Asn1EncodableVector v = new Asn1EncodableVector(certOrEncCert);
+
+ if (privateKey != null)
+ {
+ v.Add(new DerTaggedObject(true, 0, privateKey));
+ }
+
+ if (publicationInfo != null)
+ {
+ v.Add(new DerTaggedObject(true, 1, publicationInfo));
+ }
+
+ return new DerSequence(v);
+ }
+ }
+}
diff --git a/Crypto/src/asn1/cmp/Challenge.cs b/Crypto/src/asn1/cmp/Challenge.cs
new file mode 100644
index 000000000..bee5f96f5
--- /dev/null
+++ b/Crypto/src/asn1/cmp/Challenge.cs
@@ -0,0 +1,79 @@
+using System;
+
+using Org.BouncyCastle.Asn1.X509;
+
+namespace Org.BouncyCastle.Asn1.Cmp
+{
+ public class Challenge
+ : Asn1Encodable
+ {
+ private readonly AlgorithmIdentifier owf;
+ private readonly Asn1OctetString witness;
+ private readonly Asn1OctetString challenge;
+
+ private Challenge(Asn1Sequence seq)
+ {
+ int index = 0;
+
+ if (seq.Count == 3)
+ {
+ owf = AlgorithmIdentifier.GetInstance(seq[index++]);
+ }
+
+ witness = Asn1OctetString.GetInstance(seq[index++]);
+ challenge = Asn1OctetString.GetInstance(seq[index]);
+ }
+
+ public static Challenge GetInstance(object obj)
+ {
+ if (obj is Challenge)
+ return (Challenge)obj;
+
+ if (obj is Asn1Sequence)
+ return new Challenge((Asn1Sequence)obj);
+
+ throw new ArgumentException("Invalid object: " + obj.GetType().Name, "obj");
+ }
+
+ public virtual AlgorithmIdentifier Owf
+ {
+ get { return owf; }
+ }
+
+ /**
+ * <pre>
+ * Challenge ::= SEQUENCE {
+ * owf AlgorithmIdentifier OPTIONAL,
+ *
+ * -- MUST be present in the first Challenge; MAY be omitted in
+ * -- any subsequent Challenge in POPODecKeyChallContent (if
+ * -- omitted, then the owf used in the immediately preceding
+ * -- Challenge is to be used).
+ *
+ * witness OCTET STRING,
+ * -- the result of applying the one-way function (owf) to a
+ * -- randomly-generated INTEGER, A. [Note that a different
+ * -- INTEGER MUST be used for each Challenge.]
+ * challenge OCTET STRING
+ * -- the encryption (under the public key for which the cert.
+ * -- request is being made) of Rand, where Rand is specified as
+ * -- Rand ::= SEQUENCE {
+ * -- int INTEGER,
+ * -- - the randomly-generated INTEGER A (above)
+ * -- sender GeneralName
+ * -- - the sender's name (as included in PKIHeader)
+ * -- }
+ * }
+ * </pre>
+ * @return a basic ASN.1 object representation.
+ */
+ public override Asn1Object ToAsn1Object()
+ {
+ Asn1EncodableVector v = new Asn1EncodableVector();
+ v.AddOptional(owf);
+ v.Add(witness);
+ v.Add(challenge);
+ return new DerSequence(v);
+ }
+ }
+}
diff --git a/Crypto/src/asn1/cmp/CmpCertificate.cs b/Crypto/src/asn1/cmp/CmpCertificate.cs
new file mode 100644
index 000000000..16ee30059
--- /dev/null
+++ b/Crypto/src/asn1/cmp/CmpCertificate.cs
@@ -0,0 +1,80 @@
+using System;
+
+using Org.BouncyCastle.Asn1.X509;
+
+namespace Org.BouncyCastle.Asn1.Cmp
+{
+ public class CmpCertificate
+ : Asn1Encodable, IAsn1Choice
+ {
+ private readonly X509CertificateStructure x509v3PKCert;
+ private readonly AttributeCertificate x509v2AttrCert;
+
+ /**
+ * Note: the addition of attribute certificates is a BC extension.
+ */
+ public CmpCertificate(AttributeCertificate x509v2AttrCert)
+ {
+ this.x509v2AttrCert = x509v2AttrCert;
+ }
+
+ public CmpCertificate(X509CertificateStructure x509v3PKCert)
+ {
+ if (x509v3PKCert.Version != 3)
+ throw new ArgumentException("only version 3 certificates allowed", "x509v3PKCert");
+
+ this.x509v3PKCert = x509v3PKCert;
+ }
+
+ public static CmpCertificate GetInstance(object obj)
+ {
+ if (obj is CmpCertificate)
+ return (CmpCertificate)obj;
+
+ if (obj is Asn1Sequence)
+ return new CmpCertificate(X509CertificateStructure.GetInstance(obj));
+
+ if (obj is Asn1TaggedObject)
+ return new CmpCertificate(AttributeCertificate.GetInstance(((Asn1TaggedObject)obj).GetObject()));
+
+ throw new ArgumentException("Invalid object: " + obj.GetType().Name, "obj");
+ }
+
+ public virtual bool IsX509v3PKCert
+ {
+ get { return x509v3PKCert != null; }
+ }
+
+ public virtual X509CertificateStructure X509v3PKCert
+ {
+ get { return x509v3PKCert; }
+ }
+
+ public virtual AttributeCertificate X509v2AttrCert
+ {
+ get { return x509v2AttrCert; }
+ }
+
+ /**
+ * <pre>
+ * CMPCertificate ::= CHOICE {
+ * x509v3PKCert Certificate
+ * x509v2AttrCert [1] AttributeCertificate
+ * }
+ * </pre>
+ * Note: the addition of attribute certificates is a BC extension.
+ *
+ * @return a basic ASN.1 object representation.
+ */
+ public override Asn1Object ToAsn1Object()
+ {
+ if (x509v2AttrCert != null)
+ {
+ // explicit following CMP conventions
+ return new DerTaggedObject(true, 1, x509v2AttrCert);
+ }
+
+ return x509v3PKCert.ToAsn1Object();
+ }
+ }
+}
diff --git a/Crypto/src/asn1/cmp/CmpObjectIdentifiers.cs b/Crypto/src/asn1/cmp/CmpObjectIdentifiers.cs
new file mode 100644
index 000000000..7e8274175
--- /dev/null
+++ b/Crypto/src/asn1/cmp/CmpObjectIdentifiers.cs
@@ -0,0 +1,106 @@
+using System;
+
+namespace Org.BouncyCastle.Asn1.Cmp
+{
+ public abstract class CmpObjectIdentifiers
+ {
+ // RFC 4210
+
+ // id-PasswordBasedMac OBJECT IDENTIFIER ::= {1 2 840 113533 7 66 13}
+ public static readonly DerObjectIdentifier passwordBasedMac = new DerObjectIdentifier("1.2.840.113533.7.66.13");
+
+ // id-DHBasedMac OBJECT IDENTIFIER ::= {1 2 840 113533 7 66 30}
+ public static readonly DerObjectIdentifier dhBasedMac = new DerObjectIdentifier("1.2.840.113533.7.66.30");
+
+ // Example InfoTypeAndValue contents include, but are not limited
+ // to, the following (un-comment in this ASN.1 module and use as
+ // appropriate for a given environment):
+ //
+ // id-it-caProtEncCert OBJECT IDENTIFIER ::= {id-it 1}
+ // CAProtEncCertValue ::= CMPCertificate
+ // id-it-signKeyPairTypes OBJECT IDENTIFIER ::= {id-it 2}
+ // SignKeyPairTypesValue ::= SEQUENCE OF AlgorithmIdentifier
+ // id-it-encKeyPairTypes OBJECT IDENTIFIER ::= {id-it 3}
+ // EncKeyPairTypesValue ::= SEQUENCE OF AlgorithmIdentifier
+ // id-it-preferredSymmAlg OBJECT IDENTIFIER ::= {id-it 4}
+ // PreferredSymmAlgValue ::= AlgorithmIdentifier
+ // id-it-caKeyUpdateInfo OBJECT IDENTIFIER ::= {id-it 5}
+ // CAKeyUpdateInfoValue ::= CAKeyUpdAnnContent
+ // id-it-currentCRL OBJECT IDENTIFIER ::= {id-it 6}
+ // CurrentCRLValue ::= CertificateList
+ // id-it-unsupportedOIDs OBJECT IDENTIFIER ::= {id-it 7}
+ // UnsupportedOIDsValue ::= SEQUENCE OF OBJECT IDENTIFIER
+ // id-it-keyPairParamReq OBJECT IDENTIFIER ::= {id-it 10}
+ // KeyPairParamReqValue ::= OBJECT IDENTIFIER
+ // id-it-keyPairParamRep OBJECT IDENTIFIER ::= {id-it 11}
+ // KeyPairParamRepValue ::= AlgorithmIdentifer
+ // id-it-revPassphrase OBJECT IDENTIFIER ::= {id-it 12}
+ // RevPassphraseValue ::= EncryptedValue
+ // id-it-implicitConfirm OBJECT IDENTIFIER ::= {id-it 13}
+ // ImplicitConfirmValue ::= NULL
+ // id-it-confirmWaitTime OBJECT IDENTIFIER ::= {id-it 14}
+ // ConfirmWaitTimeValue ::= GeneralizedTime
+ // id-it-origPKIMessage OBJECT IDENTIFIER ::= {id-it 15}
+ // OrigPKIMessageValue ::= PKIMessages
+ // id-it-suppLangTags OBJECT IDENTIFIER ::= {id-it 16}
+ // SuppLangTagsValue ::= SEQUENCE OF UTF8String
+ //
+ // where
+ //
+ // id-pkix OBJECT IDENTIFIER ::= {
+ // iso(1) identified-organization(3)
+ // dod(6) internet(1) security(5) mechanisms(5) pkix(7)}
+ // and
+ // id-it OBJECT IDENTIFIER ::= {id-pkix 4}
+ public static readonly DerObjectIdentifier it_caProtEncCert = new DerObjectIdentifier("1.3.6.1.5.5.7.4.1");
+ public static readonly DerObjectIdentifier it_signKeyPairTypes = new DerObjectIdentifier("1.3.6.1.5.5.7.4.2");
+ public static readonly DerObjectIdentifier it_encKeyPairTypes = new DerObjectIdentifier("1.3.6.1.5.5.7.4.3");
+ public static readonly DerObjectIdentifier it_preferredSymAlg = new DerObjectIdentifier("1.3.6.1.5.5.7.4.4");
+ public static readonly DerObjectIdentifier it_caKeyUpdateInfo = new DerObjectIdentifier("1.3.6.1.5.5.7.4.5");
+ public static readonly DerObjectIdentifier it_currentCRL = new DerObjectIdentifier("1.3.6.1.5.5.7.4.6");
+ public static readonly DerObjectIdentifier it_unsupportedOIDs = new DerObjectIdentifier("1.3.6.1.5.5.7.4.7");
+ public static readonly DerObjectIdentifier it_keyPairParamReq = new DerObjectIdentifier("1.3.6.1.5.5.7.4.10");
+ public static readonly DerObjectIdentifier it_keyPairParamRep = new DerObjectIdentifier("1.3.6.1.5.5.7.4.11");
+ public static readonly DerObjectIdentifier it_revPassphrase = new DerObjectIdentifier("1.3.6.1.5.5.7.4.12");
+ public static readonly DerObjectIdentifier it_implicitConfirm = new DerObjectIdentifier("1.3.6.1.5.5.7.4.13");
+ public static readonly DerObjectIdentifier it_confirmWaitTime = new DerObjectIdentifier("1.3.6.1.5.5.7.4.14");
+ public static readonly DerObjectIdentifier it_origPKIMessage = new DerObjectIdentifier("1.3.6.1.5.5.7.4.15");
+ public static readonly DerObjectIdentifier it_suppLangTags = new DerObjectIdentifier("1.3.6.1.5.5.7.4.16");
+
+ // RFC 4211
+
+ // id-pkix OBJECT IDENTIFIER ::= { iso(1) identified-organization(3)
+ // dod(6) internet(1) security(5) mechanisms(5) pkix(7) }
+ //
+ // arc for Internet X.509 PKI protocols and their components
+ // id-pkip OBJECT IDENTIFIER :: { id-pkix pkip(5) }
+ //
+ // arc for Registration Controls in CRMF
+ // id-regCtrl OBJECT IDENTIFIER ::= { id-pkip regCtrl(1) }
+ //
+ // arc for Registration Info in CRMF
+ // id-regInfo OBJECT IDENTIFIER ::= { id-pkip id-regInfo(2) }
+
+ public static readonly DerObjectIdentifier regCtrl_regToken = new DerObjectIdentifier("1.3.6.1.5.5.7.5.1.1");
+ public static readonly DerObjectIdentifier regCtrl_authenticator = new DerObjectIdentifier("1.3.6.1.5.5.7.5.1.2");
+ public static readonly DerObjectIdentifier regCtrl_pkiPublicationInfo = new DerObjectIdentifier("1.3.6.1.5.5.7.5.1.3");
+ public static readonly DerObjectIdentifier regCtrl_pkiArchiveOptions = new DerObjectIdentifier("1.3.6.1.5.5.7.5.1.4");
+ public static readonly DerObjectIdentifier regCtrl_oldCertID = new DerObjectIdentifier("1.3.6.1.5.5.7.5.1.5");
+ public static readonly DerObjectIdentifier regCtrl_protocolEncrKey = new DerObjectIdentifier("1.3.6.1.5.5.7.5.1.6");
+
+ // From RFC4210:
+ // id-regCtrl-altCertTemplate OBJECT IDENTIFIER ::= {id-regCtrl 7}
+ public static readonly DerObjectIdentifier regCtrl_altCertTemplate = new DerObjectIdentifier("1.3.6.1.5.5.7.5.1.7");
+
+ public static readonly DerObjectIdentifier regInfo_utf8Pairs = new DerObjectIdentifier("1.3.6.1.5.5.7.5.2.1");
+ public static readonly DerObjectIdentifier regInfo_certReq = new DerObjectIdentifier("1.3.6.1.5.5.7.5.2.2");
+
+ // id-smime OBJECT IDENTIFIER ::= { iso(1) member-body(2)
+ // us(840) rsadsi(113549) pkcs(1) pkcs9(9) 16 }
+ //
+ // id-ct OBJECT IDENTIFIER ::= { id-smime 1 } -- content types
+ //
+ // id-ct-encKeyWithID OBJECT IDENTIFIER ::= {id-ct 21}
+ public static readonly DerObjectIdentifier ct_encKeyWithID = new DerObjectIdentifier("1.2.840.113549.1.9.16.1.21");
+ }
+}
diff --git a/Crypto/src/asn1/cmp/CrlAnnContent.cs b/Crypto/src/asn1/cmp/CrlAnnContent.cs
new file mode 100644
index 000000000..3dc11d32c
--- /dev/null
+++ b/Crypto/src/asn1/cmp/CrlAnnContent.cs
@@ -0,0 +1,49 @@
+using System;
+
+using Org.BouncyCastle.Asn1.X509;
+
+namespace Org.BouncyCastle.Asn1.Cmp
+{
+ public class CrlAnnContent
+ : Asn1Encodable
+ {
+ private readonly Asn1Sequence content;
+
+ private CrlAnnContent(Asn1Sequence seq)
+ {
+ content = seq;
+ }
+
+ public static CrlAnnContent GetInstance(object obj)
+ {
+ if (obj is CrlAnnContent)
+ return (CrlAnnContent)obj;
+
+ if (obj is Asn1Sequence)
+ return new CrlAnnContent((Asn1Sequence)obj);
+
+ throw new ArgumentException("Invalid object: " + obj.GetType().Name, "obj");
+ }
+
+ public virtual CertificateList[] ToCertificateListArray()
+ {
+ CertificateList[] result = new CertificateList[content.Count];
+ for (int i = 0; i != result.Length; ++ i)
+ {
+ result[i] = CertificateList.GetInstance(content[i]);
+ }
+ return result;
+ }
+
+ /**
+ * <pre>
+ * CrlAnnContent ::= SEQUENCE OF CertificateList
+ * </pre>
+ * @return a basic ASN.1 object representation.
+ */
+ public override Asn1Object ToAsn1Object()
+ {
+ return content;
+ }
+ }
+}
diff --git a/Crypto/src/asn1/cmp/ErrorMsgContent.cs b/Crypto/src/asn1/cmp/ErrorMsgContent.cs
new file mode 100644
index 000000000..f4dc584ea
--- /dev/null
+++ b/Crypto/src/asn1/cmp/ErrorMsgContent.cs
@@ -0,0 +1,94 @@
+using System;
+
+namespace Org.BouncyCastle.Asn1.Cmp
+{
+ public class ErrorMsgContent
+ : Asn1Encodable
+ {
+ private readonly PkiStatusInfo pkiStatusInfo;
+ private readonly DerInteger errorCode;
+ private readonly PkiFreeText errorDetails;
+
+ private ErrorMsgContent(Asn1Sequence seq)
+ {
+ pkiStatusInfo = PkiStatusInfo.GetInstance(seq[0]);
+
+ for (int pos = 1; pos < seq.Count; ++pos)
+ {
+ Asn1Encodable ae = seq[pos];
+ if (ae is DerInteger)
+ {
+ errorCode = DerInteger.GetInstance(ae);
+ }
+ else
+ {
+ errorDetails = PkiFreeText.GetInstance(ae);
+ }
+ }
+ }
+
+ public static ErrorMsgContent GetInstance(object obj)
+ {
+ if (obj is ErrorMsgContent)
+ return (ErrorMsgContent)obj;
+
+ if (obj is Asn1Sequence)
+ return new ErrorMsgContent((Asn1Sequence)obj);
+
+ throw new ArgumentException("Invalid object: " + obj.GetType().Name, "obj");
+ }
+
+ public ErrorMsgContent(PkiStatusInfo pkiStatusInfo)
+ : this(pkiStatusInfo, null, null)
+ {
+ }
+
+ public ErrorMsgContent(
+ PkiStatusInfo pkiStatusInfo,
+ DerInteger errorCode,
+ PkiFreeText errorDetails)
+ {
+ if (pkiStatusInfo == null)
+ throw new ArgumentNullException("pkiStatusInfo");
+
+ this.pkiStatusInfo = pkiStatusInfo;
+ this.errorCode = errorCode;
+ this.errorDetails = errorDetails;
+ }
+
+ public virtual PkiStatusInfo PkiStatusInfo
+ {
+ get { return pkiStatusInfo; }
+ }
+
+ public virtual DerInteger ErrorCode
+ {
+ get { return errorCode; }
+ }
+
+ public virtual PkiFreeText ErrorDetails
+ {
+ get { return errorDetails; }
+ }
+
+ /**
+ * <pre>
+ * ErrorMsgContent ::= SEQUENCE {
+ * pKIStatusInfo PKIStatusInfo,
+ * errorCode INTEGER OPTIONAL,
+ * -- implementation-specific error codes
+ * errorDetails PKIFreeText OPTIONAL
+ * -- implementation-specific error details
+ * }
+ * </pre>
+ * @return a basic ASN.1 object representation.
+ */
+ public override Asn1Object ToAsn1Object()
+ {
+ Asn1EncodableVector v = new Asn1EncodableVector(pkiStatusInfo);
+ v.AddOptional(errorCode);
+ v.AddOptional(errorDetails);
+ return new DerSequence(v);
+ }
+ }
+}
diff --git a/Crypto/src/asn1/cmp/GenMsgContent.cs b/Crypto/src/asn1/cmp/GenMsgContent.cs
new file mode 100644
index 000000000..9f042491c
--- /dev/null
+++ b/Crypto/src/asn1/cmp/GenMsgContent.cs
@@ -0,0 +1,52 @@
+using System;
+
+namespace Org.BouncyCastle.Asn1.Cmp
+{
+ public class GenMsgContent
+ : Asn1Encodable
+ {
+ private readonly Asn1Sequence content;
+
+ private GenMsgContent(Asn1Sequence seq)
+ {
+ content = seq;
+ }
+
+ public static GenMsgContent GetInstance(object obj)
+ {
+ if (obj is GenMsgContent)
+ return (GenMsgContent)obj;
+
+ if (obj is Asn1Sequence)
+ return new GenMsgContent((Asn1Sequence)obj);
+
+ throw new ArgumentException("Invalid object: " + obj.GetType().Name, "obj");
+ }
+
+ public GenMsgContent(params InfoTypeAndValue[] itv)
+ {
+ content = new DerSequence(itv);
+ }
+
+ public virtual InfoTypeAndValue[] ToInfoTypeAndValueArray()
+ {
+ InfoTypeAndValue[] result = new InfoTypeAndValue[content.Count];
+ for (int i = 0; i != result.Length; ++i)
+ {
+ result[i] = InfoTypeAndValue.GetInstance(content[i]);
+ }
+ return result;
+ }
+
+ /**
+ * <pre>
+ * GenMsgContent ::= SEQUENCE OF InfoTypeAndValue
+ * </pre>
+ * @return a basic ASN.1 object representation.
+ */
+ public override Asn1Object ToAsn1Object()
+ {
+ return content;
+ }
+ }
+}
diff --git a/Crypto/src/asn1/cmp/GenRepContent.cs b/Crypto/src/asn1/cmp/GenRepContent.cs
new file mode 100644
index 000000000..5bdc5550a
--- /dev/null
+++ b/Crypto/src/asn1/cmp/GenRepContent.cs
@@ -0,0 +1,52 @@
+using System;
+
+namespace Org.BouncyCastle.Asn1.Cmp
+{
+ public class GenRepContent
+ : Asn1Encodable
+ {
+ private readonly Asn1Sequence content;
+
+ private GenRepContent(Asn1Sequence seq)
+ {
+ content = seq;
+ }
+
+ public static GenRepContent GetInstance(object obj)
+ {
+ if (obj is GenRepContent)
+ return (GenRepContent)obj;
+
+ if (obj is Asn1Sequence)
+ return new GenRepContent((Asn1Sequence)obj);
+
+ throw new ArgumentException("Invalid object: " + obj.GetType().Name, "obj");
+ }
+
+ public GenRepContent(params InfoTypeAndValue[] itv)
+ {
+ content = new DerSequence(itv);
+ }
+
+ public virtual InfoTypeAndValue[] ToInfoTypeAndValueArray()
+ {
+ InfoTypeAndValue[] result = new InfoTypeAndValue[content.Count];
+ for (int i = 0; i != result.Length; ++i)
+ {
+ result[i] = InfoTypeAndValue.GetInstance(content[i]);
+ }
+ return result;
+ }
+
+ /**
+ * <pre>
+ * GenRepContent ::= SEQUENCE OF InfoTypeAndValue
+ * </pre>
+ * @return a basic ASN.1 object representation.
+ */
+ public override Asn1Object ToAsn1Object()
+ {
+ return content;
+ }
+ }
+}
diff --git a/Crypto/src/asn1/cmp/InfoTypeAndValue.cs b/Crypto/src/asn1/cmp/InfoTypeAndValue.cs
new file mode 100644
index 000000000..9b51dba02
--- /dev/null
+++ b/Crypto/src/asn1/cmp/InfoTypeAndValue.cs
@@ -0,0 +1,121 @@
+using System;
+
+namespace Org.BouncyCastle.Asn1.Cmp
+{
+ /**
+ * Example InfoTypeAndValue contents include, but are not limited
+ * to, the following (un-comment in this ASN.1 module and use as
+ * appropriate for a given environment):
+ * <pre>
+ * id-it-caProtEncCert OBJECT IDENTIFIER ::= {id-it 1}
+ * CAProtEncCertValue ::= CMPCertificate
+ * id-it-signKeyPairTypes OBJECT IDENTIFIER ::= {id-it 2}
+ * SignKeyPairTypesValue ::= SEQUENCE OF AlgorithmIdentifier
+ * id-it-encKeyPairTypes OBJECT IDENTIFIER ::= {id-it 3}
+ * EncKeyPairTypesValue ::= SEQUENCE OF AlgorithmIdentifier
+ * id-it-preferredSymmAlg OBJECT IDENTIFIER ::= {id-it 4}
+ * PreferredSymmAlgValue ::= AlgorithmIdentifier
+ * id-it-caKeyUpdateInfo OBJECT IDENTIFIER ::= {id-it 5}
+ * CAKeyUpdateInfoValue ::= CAKeyUpdAnnContent
+ * id-it-currentCRL OBJECT IDENTIFIER ::= {id-it 6}
+ * CurrentCRLValue ::= CertificateList
+ * id-it-unsupportedOIDs OBJECT IDENTIFIER ::= {id-it 7}
+ * UnsupportedOIDsValue ::= SEQUENCE OF OBJECT IDENTIFIER
+ * id-it-keyPairParamReq OBJECT IDENTIFIER ::= {id-it 10}
+ * KeyPairParamReqValue ::= OBJECT IDENTIFIER
+ * id-it-keyPairParamRep OBJECT IDENTIFIER ::= {id-it 11}
+ * KeyPairParamRepValue ::= AlgorithmIdentifer
+ * id-it-revPassphrase OBJECT IDENTIFIER ::= {id-it 12}
+ * RevPassphraseValue ::= EncryptedValue
+ * id-it-implicitConfirm OBJECT IDENTIFIER ::= {id-it 13}
+ * ImplicitConfirmValue ::= NULL
+ * id-it-confirmWaitTime OBJECT IDENTIFIER ::= {id-it 14}
+ * ConfirmWaitTimeValue ::= GeneralizedTime
+ * id-it-origPKIMessage OBJECT IDENTIFIER ::= {id-it 15}
+ * OrigPKIMessageValue ::= PKIMessages
+ * id-it-suppLangTags OBJECT IDENTIFIER ::= {id-it 16}
+ * SuppLangTagsValue ::= SEQUENCE OF UTF8String
+ *
+ * where
+ *
+ * id-pkix OBJECT IDENTIFIER ::= {
+ * iso(1) identified-organization(3)
+ * dod(6) internet(1) security(5) mechanisms(5) pkix(7)}
+ * and
+ * id-it OBJECT IDENTIFIER ::= {id-pkix 4}
+ * </pre>
+ */
+ public class InfoTypeAndValue
+ : Asn1Encodable
+ {
+ private readonly DerObjectIdentifier infoType;
+ private readonly Asn1Encodable infoValue;
+
+ private InfoTypeAndValue(Asn1Sequence seq)
+ {
+ infoType = DerObjectIdentifier.GetInstance(seq[0]);
+
+ if (seq.Count > 1)
+ {
+ infoValue = (Asn1Encodable)seq[1];
+ }
+ }
+
+ public static InfoTypeAndValue GetInstance(object obj)
+ {
+ if (obj is InfoTypeAndValue)
+ return (InfoTypeAndValue)obj;
+
+ if (obj is Asn1Sequence)
+ return new InfoTypeAndValue((Asn1Sequence)obj);
+
+ throw new ArgumentException("Invalid object: " + obj.GetType().Name, "obj");
+ }
+
+ public InfoTypeAndValue(
+ DerObjectIdentifier infoType)
+ {
+ this.infoType = infoType;
+ this.infoValue = null;
+ }
+
+ public InfoTypeAndValue(
+ DerObjectIdentifier infoType,
+ Asn1Encodable optionalValue)
+ {
+ this.infoType = infoType;
+ this.infoValue = optionalValue;
+ }
+
+ public virtual DerObjectIdentifier InfoType
+ {
+ get { return infoType; }
+ }
+
+ public virtual Asn1Encodable InfoValue
+ {
+ get { return infoValue; }
+ }
+
+ /**
+ * <pre>
+ * InfoTypeAndValue ::= SEQUENCE {
+ * infoType OBJECT IDENTIFIER,
+ * infoValue ANY DEFINED BY infoType OPTIONAL
+ * }
+ * </pre>
+ * @return a basic ASN.1 object representation.
+ */
+ public override Asn1Object ToAsn1Object()
+ {
+ Asn1EncodableVector v = new Asn1EncodableVector(infoType);
+
+ if (infoValue != null)
+ {
+ v.Add(infoValue);
+ }
+
+ return new DerSequence(v);
+ }
+ }
+}
diff --git a/Crypto/src/asn1/cmp/KeyRecRepContent.cs b/Crypto/src/asn1/cmp/KeyRecRepContent.cs
new file mode 100644
index 000000000..b0352f048
--- /dev/null
+++ b/Crypto/src/asn1/cmp/KeyRecRepContent.cs
@@ -0,0 +1,115 @@
+using System;
+
+namespace Org.BouncyCastle.Asn1.Cmp
+{
+ public class KeyRecRepContent
+ : Asn1Encodable
+ {
+ private readonly PkiStatusInfo status;
+ private readonly CmpCertificate newSigCert;
+ private readonly Asn1Sequence caCerts;
+ private readonly Asn1Sequence keyPairHist;
+
+ private KeyRecRepContent(Asn1Sequence seq)
+ {
+ status = PkiStatusInfo.GetInstance(seq[0]);
+
+ for (int pos = 1; pos < seq.Count; ++pos)
+ {
+ Asn1TaggedObject tObj = Asn1TaggedObject.GetInstance(seq[pos]);
+
+ switch (tObj.TagNo)
+ {
+ case 0:
+ newSigCert = CmpCertificate.GetInstance(tObj.GetObject());
+ break;
+ case 1:
+ caCerts = Asn1Sequence.GetInstance(tObj.GetObject());
+ break;
+ case 2:
+ keyPairHist = Asn1Sequence.GetInstance(tObj.GetObject());
+ break;
+ default:
+ throw new ArgumentException("unknown tag number: " + tObj.TagNo, "seq");
+ }
+ }
+ }
+
+ public static KeyRecRepContent GetInstance(object obj)
+ {
+ if (obj is KeyRecRepContent)
+ return (KeyRecRepContent)obj;
+
+ if (obj is Asn1Sequence)
+ return new KeyRecRepContent((Asn1Sequence)obj);
+
+ throw new ArgumentException("Invalid object: " + obj.GetType().Name, "obj");
+ }
+
+ public virtual PkiStatusInfo Status
+ {
+ get { return status; }
+ }
+
+ public virtual CmpCertificate NewSigCert
+ {
+ get { return newSigCert; }
+ }
+
+ public virtual CmpCertificate[] GetCACerts()
+ {
+ if (caCerts == null)
+ return null;
+
+ CmpCertificate[] results = new CmpCertificate[caCerts.Count];
+ for (int i = 0; i != results.Length; ++i)
+ {
+ results[i] = CmpCertificate.GetInstance(caCerts[i]);
+ }
+ return results;
+ }
+
+ public virtual CertifiedKeyPair[] GetKeyPairHist()
+ {
+ if (keyPairHist == null)
+ return null;
+
+ CertifiedKeyPair[] results = new CertifiedKeyPair[keyPairHist.Count];
+ for (int i = 0; i != results.Length; ++i)
+ {
+ results[i] = CertifiedKeyPair.GetInstance(keyPairHist[i]);
+ }
+ return results;
+ }
+
+ /**
+ * <pre>
+ * KeyRecRepContent ::= SEQUENCE {
+ * status PKIStatusInfo,
+ * newSigCert [0] CMPCertificate OPTIONAL,
+ * caCerts [1] SEQUENCE SIZE (1..MAX) OF
+ * CMPCertificate OPTIONAL,
+ * keyPairHist [2] SEQUENCE SIZE (1..MAX) OF
+ * CertifiedKeyPair OPTIONAL
+ * }
+ * </pre>
+ * @return a basic ASN.1 object representation.
+ */
+ public override Asn1Object ToAsn1Object()
+ {
+ Asn1EncodableVector v = new Asn1EncodableVector(status);
+ AddOptional(v, 0, newSigCert);
+ AddOptional(v, 1, caCerts);
+ AddOptional(v, 2, keyPairHist);
+ return new DerSequence(v);
+ }
+
+ private void AddOptional(Asn1EncodableVector v, int tagNo, Asn1Encodable obj)
+ {
+ if (obj != null)
+ {
+ v.Add(new DerTaggedObject(true, tagNo, obj));
+ }
+ }
+ }
+}
diff --git a/Crypto/src/asn1/cmp/OobCertHash.cs b/Crypto/src/asn1/cmp/OobCertHash.cs
new file mode 100644
index 000000000..63ddff7c4
--- /dev/null
+++ b/Crypto/src/asn1/cmp/OobCertHash.cs
@@ -0,0 +1,87 @@
+using System;
+
+using Org.BouncyCastle.Asn1.Crmf;
+using Org.BouncyCastle.Asn1.X509;
+
+namespace Org.BouncyCastle.Asn1.Cmp
+{
+ public class OobCertHash
+ : Asn1Encodable
+ {
+ private readonly AlgorithmIdentifier hashAlg;
+ private readonly CertId certId;
+ private readonly DerBitString hashVal;
+
+ private OobCertHash(Asn1Sequence seq)
+ {
+ int index = seq.Count - 1;
+
+ hashVal = DerBitString.GetInstance(seq[index--]);
+
+ for (int i = index; i >= 0; i--)
+ {
+ Asn1TaggedObject tObj = (Asn1TaggedObject)seq[i];
+
+ if (tObj.TagNo == 0)
+ {
+ hashAlg = AlgorithmIdentifier.GetInstance(tObj, true);
+ }
+ else
+ {
+ certId = CertId.GetInstance(tObj, true);
+ }
+ }
+ }
+
+ public static OobCertHash GetInstance(object obj)
+ {
+ if (obj is OobCertHash)
+ return (OobCertHash)obj;
+
+ if (obj is Asn1Sequence)
+ return new OobCertHash((Asn1Sequence)obj);
+
+ throw new ArgumentException("Invalid object: " + obj.GetType().Name, "obj");
+ }
+
+ public virtual AlgorithmIdentifier HashAlg
+ {
+ get { return hashAlg; }
+ }
+
+ public virtual CertId CertID
+ {
+ get { return certId; }
+ }
+
+ /**
+ * <pre>
+ * OobCertHash ::= SEQUENCE {
+ * hashAlg [0] AlgorithmIdentifier OPTIONAL,
+ * certId [1] CertId OPTIONAL,
+ * hashVal BIT STRING
+ * -- hashVal is calculated over the Der encoding of the
+ * -- self-signed certificate with the identifier certID.
+ * }
+ * </pre>
+ * @return a basic ASN.1 object representation.
+ */
+ public override Asn1Object ToAsn1Object()
+ {
+ Asn1EncodableVector v = new Asn1EncodableVector();
+ AddOptional(v, 0, hashAlg);
+ AddOptional(v, 1, certId);
+ v.Add(hashVal);
+ return new DerSequence(v);
+ }
+
+ private void AddOptional(Asn1EncodableVector v, int tagNo, Asn1Encodable obj)
+ {
+ if (obj != null)
+ {
+ v.Add(new DerTaggedObject(true, tagNo, obj));
+ }
+ }
+ }
+}
+
diff --git a/Crypto/src/asn1/cmp/PKIBody.cs b/Crypto/src/asn1/cmp/PKIBody.cs
new file mode 100644
index 000000000..3205a907e
--- /dev/null
+++ b/Crypto/src/asn1/cmp/PKIBody.cs
@@ -0,0 +1,186 @@
+using System;
+
+using Org.BouncyCastle.Asn1.Crmf;
+using Org.BouncyCastle.Asn1.Pkcs;
+
+namespace Org.BouncyCastle.Asn1.Cmp
+{
+ public class PkiBody
+ : Asn1Encodable, IAsn1Choice
+ {
+ public const int TYPE_INIT_REQ = 0;
+ public const int TYPE_INIT_REP = 1;
+ public const int TYPE_CERT_REQ = 2;
+ public const int TYPE_CERT_REP = 3;
+ public const int TYPE_P10_CERT_REQ = 4;
+ public const int TYPE_POPO_CHALL = 5;
+ public const int TYPE_POPO_REP = 6;
+ public const int TYPE_KEY_UPDATE_REQ = 7;
+ public const int TYPE_KEY_UPDATE_REP = 8;
+ public const int TYPE_KEY_RECOVERY_REQ = 9;
+ public const int TYPE_KEY_RECOVERY_REP = 10;
+ public const int TYPE_REVOCATION_REQ = 11;
+ public const int TYPE_REVOCATION_REP = 12;
+ public const int TYPE_CROSS_CERT_REQ = 13;
+ public const int TYPE_CROSS_CERT_REP = 14;
+ public const int TYPE_CA_KEY_UPDATE_ANN = 15;
+ public const int TYPE_CERT_ANN = 16;
+ public const int TYPE_REVOCATION_ANN = 17;
+ public const int TYPE_CRL_ANN = 18;
+ public const int TYPE_CONFIRM = 19;
+ public const int TYPE_NESTED = 20;
+ public const int TYPE_GEN_MSG = 21;
+ public const int TYPE_GEN_REP = 22;
+ public const int TYPE_ERROR = 23;
+ public const int TYPE_CERT_CONFIRM = 24;
+ public const int TYPE_POLL_REQ = 25;
+ public const int TYPE_POLL_REP = 26;
+
+ private int tagNo;
+ private Asn1Encodable body;
+
+ public static PkiBody GetInstance(object obj)
+ {
+ if (obj is PkiBody)
+ return (PkiBody)obj;
+
+ if (obj is Asn1TaggedObject)
+ return new PkiBody((Asn1TaggedObject)obj);
+
+ throw new ArgumentException("Invalid object: " + obj.GetType().Name, "obj");
+ }
+
+ private PkiBody(Asn1TaggedObject tagged)
+ {
+ tagNo = tagged.TagNo;
+ body = GetBodyForType(tagNo, tagged.GetObject());
+ }
+
+ /**
+ * Creates a new PkiBody.
+ * @param type one of the TYPE_* constants
+ * @param content message content
+ */
+ public PkiBody(
+ int type,
+ Asn1Encodable content)
+ {
+ tagNo = type;
+ body = GetBodyForType(type, content);
+ }
+
+ private static Asn1Encodable GetBodyForType(
+ int type,
+ Asn1Encodable o)
+ {
+ switch (type)
+ {
+ case TYPE_INIT_REQ:
+ return CertReqMessages.GetInstance(o);
+ case TYPE_INIT_REP:
+ return CertRepMessage.GetInstance(o);
+ case TYPE_CERT_REQ:
+ return CertReqMessages.GetInstance(o);
+ case TYPE_CERT_REP:
+ return CertRepMessage.GetInstance(o);
+ case TYPE_P10_CERT_REQ:
+ return CertificationRequest.GetInstance(o);
+ case TYPE_POPO_CHALL:
+ return PopoDecKeyChallContent.GetInstance(o);
+ case TYPE_POPO_REP:
+ return PopoDecKeyRespContent.GetInstance(o);
+ case TYPE_KEY_UPDATE_REQ:
+ return CertReqMessages.GetInstance(o);
+ case TYPE_KEY_UPDATE_REP:
+ return CertRepMessage.GetInstance(o);
+ case TYPE_KEY_RECOVERY_REQ:
+ return CertReqMessages.GetInstance(o);
+ case TYPE_KEY_RECOVERY_REP:
+ return KeyRecRepContent.GetInstance(o);
+ case TYPE_REVOCATION_REQ:
+ return RevReqContent.GetInstance(o);
+ case TYPE_REVOCATION_REP:
+ return RevRepContent.GetInstance(o);
+ case TYPE_CROSS_CERT_REQ:
+ return CertReqMessages.GetInstance(o);
+ case TYPE_CROSS_CERT_REP:
+ return CertRepMessage.GetInstance(o);
+ case TYPE_CA_KEY_UPDATE_ANN:
+ return CAKeyUpdAnnContent.GetInstance(o);
+ case TYPE_CERT_ANN:
+ return CmpCertificate.GetInstance(o);
+ case TYPE_REVOCATION_ANN:
+ return RevAnnContent.GetInstance(o);
+ case TYPE_CRL_ANN:
+ return CrlAnnContent.GetInstance(o);
+ case TYPE_CONFIRM:
+ return PkiConfirmContent.GetInstance(o);
+ case TYPE_NESTED:
+ return PkiMessages.GetInstance(o);
+ case TYPE_GEN_MSG:
+ return GenMsgContent.GetInstance(o);
+ case TYPE_GEN_REP:
+ return GenRepContent.GetInstance(o);
+ case TYPE_ERROR:
+ return ErrorMsgContent.GetInstance(o);
+ case TYPE_CERT_CONFIRM:
+ return CertConfirmContent.GetInstance(o);
+ case TYPE_POLL_REQ:
+ return PollReqContent.GetInstance(o);
+ case TYPE_POLL_REP:
+ return PollRepContent.GetInstance(o);
+ default:
+ throw new ArgumentException("unknown tag number: " + type, "type");
+ }
+ }
+
+ public virtual int Type
+ {
+ get { return tagNo; }
+ }
+
+ public virtual Asn1Encodable Content
+ {
+ get { return body; }
+ }
+
+ /**
+ * <pre>
+ * PkiBody ::= CHOICE { -- message-specific body elements
+ * ir [0] CertReqMessages, --Initialization Request
+ * ip [1] CertRepMessage, --Initialization Response
+ * cr [2] CertReqMessages, --Certification Request
+ * cp [3] CertRepMessage, --Certification Response
+ * p10cr [4] CertificationRequest, --imported from [PKCS10]
+ * popdecc [5] POPODecKeyChallContent, --pop Challenge
+ * popdecr [6] POPODecKeyRespContent, --pop Response
+ * kur [7] CertReqMessages, --Key Update Request
+ * kup [8] CertRepMessage, --Key Update Response
+ * krr [9] CertReqMessages, --Key Recovery Request
+ * krp [10] KeyRecRepContent, --Key Recovery Response
+ * rr [11] RevReqContent, --Revocation Request
+ * rp [12] RevRepContent, --Revocation Response
+ * ccr [13] CertReqMessages, --Cross-Cert. Request
+ * ccp [14] CertRepMessage, --Cross-Cert. Response
+ * ckuann [15] CAKeyUpdAnnContent, --CA Key Update Ann.
+ * cann [16] CertAnnContent, --Certificate Ann.
+ * rann [17] RevAnnContent, --Revocation Ann.
+ * crlann [18] CRLAnnContent, --CRL Announcement
+ * pkiconf [19] PKIConfirmContent, --Confirmation
+ * nested [20] NestedMessageContent, --Nested Message
+ * genm [21] GenMsgContent, --General Message
+ * genp [22] GenRepContent, --General Response
+ * error [23] ErrorMsgContent, --Error Message
+ * certConf [24] CertConfirmContent, --Certificate confirm
+ * pollReq [25] PollReqContent, --Polling request
+ * pollRep [26] PollRepContent --Polling response
+ * }
+ * </pre>
+ * @return a basic ASN.1 object representation.
+ */
+ public override Asn1Object ToAsn1Object()
+ {
+ return new DerTaggedObject(true, tagNo, body);
+ }
+ }
+}
diff --git a/Crypto/src/asn1/cmp/PKIConfirmContent.cs b/Crypto/src/asn1/cmp/PKIConfirmContent.cs
new file mode 100644
index 000000000..98645766a
--- /dev/null
+++ b/Crypto/src/asn1/cmp/PKIConfirmContent.cs
@@ -0,0 +1,34 @@
+using System;
+
+namespace Org.BouncyCastle.Asn1.Cmp
+{
+ public class PkiConfirmContent
+ : Asn1Encodable
+ {
+ public static PkiConfirmContent GetInstance(object obj)
+ {
+ if (obj is PkiConfirmContent)
+ return (PkiConfirmContent)obj;
+
+ if (obj is Asn1Null)
+ return new PkiConfirmContent();
+
+ throw new ArgumentException("Invalid object: " + obj.GetType().Name, "obj");
+ }
+
+ public PkiConfirmContent()
+ {
+ }
+
+ /**
+ * <pre>
+ * PkiConfirmContent ::= NULL
+ * </pre>
+ * @return a basic ASN.1 object representation.
+ */
+ public override Asn1Object ToAsn1Object()
+ {
+ return DerNull.Instance;
+ }
+ }
+}
diff --git a/Crypto/src/asn1/cmp/PKIFailureInfo.cs b/Crypto/src/asn1/cmp/PKIFailureInfo.cs
new file mode 100644
index 000000000..1df0e0693
--- /dev/null
+++ b/Crypto/src/asn1/cmp/PKIFailureInfo.cs
@@ -0,0 +1,73 @@
+using System;
+
+namespace Org.BouncyCastle.Asn1.Cmp
+{
+ /**
+ * <pre>
+ * PKIFailureInfo ::= BIT STRING {
+ * badAlg (0),
+ * -- unrecognized or unsupported Algorithm Identifier
+ * badMessageCheck (1), -- integrity check failed (e.g., signature did not verify)
+ * badRequest (2),
+ * -- transaction not permitted or supported
+ * badTime (3), -- messageTime was not sufficiently close to the system time, as defined by local policy
+ * badCertId (4), -- no certificate could be found matching the provided criteria
+ * badDataFormat (5),
+ * -- the data submitted has the wrong format
+ * wrongAuthority (6), -- the authority indicated in the request is different from the one creating the response token
+ * incorrectData (7), -- the requester's data is incorrect (for notary services)
+ * missingTimeStamp (8), -- when the timestamp is missing but should be there (by policy)
+ * badPOP (9) -- the proof-of-possession failed
+ * timeNotAvailable (14),
+ * -- the TSA's time source is not available
+ * unacceptedPolicy (15),
+ * -- the requested TSA policy is not supported by the TSA
+ * unacceptedExtension (16),
+ * -- the requested extension is not supported by the TSA
+ * addInfoNotAvailable (17)
+ * -- the additional information requested could not be understood
+ * -- or is not available
+ * systemFailure (25)
+ * -- the request cannot be handled due to system failure
+ * </pre>
+ */
+ public class PkiFailureInfo
+ : DerBitString
+ {
+ public const int BadAlg = (1 << 7); // unrecognized or unsupported Algorithm Identifier
+ public const int BadMessageCheck = (1 << 6); // integrity check failed (e.g., signature did not verify)
+ public const int BadRequest = (1 << 5);
+ public const int BadTime = (1 << 4); // -- messageTime was not sufficiently close to the system time, as defined by local policy
+ public const int BadCertId = (1 << 3); // no certificate could be found matching the provided criteria
+ public const int BadDataFormat = (1 << 2);
+ public const int WrongAuthority = (1 << 1); // the authority indicated in the request is different from the one creating the response token
+ public const int IncorrectData = 1; // the requester's data is incorrect (for notary services)
+ public const int MissingTimeStamp = (1 << 15); // when the timestamp is missing but should be there (by policy)
+ public const int BadPop = (1 << 14); // the proof-of-possession failed
+ public const int TimeNotAvailable = (1 << 9); // the TSA's time source is not available
+ public const int UnacceptedPolicy = (1 << 8); // the requested TSA policy is not supported by the TSA
+ public const int UnacceptedExtension = (1 << 23); //the requested extension is not supported by the TSA
+ public const int AddInfoNotAvailable = (1 << 22); //the additional information requested could not be understood or is not available
+ public const int SystemFailure = (1 << 30); //the request cannot be handled due to system failure
+
+ /**
+ * Basic constructor.
+ */
+ public PkiFailureInfo(
+ int info)
+ : base(GetBytes(info), GetPadBits(info))
+ {
+ }
+
+ public PkiFailureInfo(
+ DerBitString info)
+ : base(info.GetBytes(), info.PadBits)
+ {
+ }
+
+ public override string ToString()
+ {
+ return "PkiFailureInfo: 0x" + this.IntValue.ToString("X");
+ }
+ }
+}
diff --git a/Crypto/src/asn1/cmp/PKIFreeText.cs b/Crypto/src/asn1/cmp/PKIFreeText.cs
new file mode 100644
index 000000000..571c8d93a
--- /dev/null
+++ b/Crypto/src/asn1/cmp/PKIFreeText.cs
@@ -0,0 +1,97 @@
+using System;
+using System.Collections;
+
+namespace Org.BouncyCastle.Asn1.Cmp
+{
+ public class PkiFreeText
+ : Asn1Encodable
+ {
+ internal Asn1Sequence strings;
+
+ public static PkiFreeText GetInstance(
+ Asn1TaggedObject obj,
+ bool isExplicit)
+ {
+ return GetInstance(Asn1Sequence.GetInstance(obj, isExplicit));
+ }
+
+ public static PkiFreeText GetInstance(
+ object obj)
+ {
+ if (obj is PkiFreeText)
+ {
+ return (PkiFreeText)obj;
+ }
+ else if (obj is Asn1Sequence)
+ {
+ return new PkiFreeText((Asn1Sequence)obj);
+ }
+
+ throw new ArgumentException("Unknown object in factory: " + obj.GetType().Name, "obj");
+ }
+
+ public PkiFreeText(
+ Asn1Sequence seq)
+ {
+ foreach (object o in seq)
+ {
+ if (!(o is DerUtf8String))
+ {
+ throw new ArgumentException("attempt to insert non UTF8 STRING into PkiFreeText");
+ }
+ }
+
+ this.strings = seq;
+ }
+
+ public PkiFreeText(
+ DerUtf8String p)
+ {
+ strings = new DerSequence(p);
+ }
+
+ /**
+ * Return the number of string elements present.
+ *
+ * @return number of elements present.
+ */
+ [Obsolete("Use 'Count' property instead")]
+ public int Size
+ {
+ get { return strings.Count; }
+ }
+
+ public int Count
+ {
+ get { return strings.Count; }
+ }
+
+ /**
+ * Return the UTF8STRING at index.
+ *
+ * @param index index of the string of interest
+ * @return the string at index.
+ */
+ public DerUtf8String this[int index]
+ {
+ get { return (DerUtf8String) strings[index]; }
+ }
+
+ [Obsolete("Use 'object[index]' syntax instead")]
+ public DerUtf8String GetStringAt(
+ int index)
+ {
+ return this[index];
+ }
+
+ /**
+ * <pre>
+ * PkiFreeText ::= SEQUENCE SIZE (1..MAX) OF UTF8String
+ * </pre>
+ */
+ public override Asn1Object ToAsn1Object()
+ {
+ return strings;
+ }
+ }
+}
diff --git a/Crypto/src/asn1/cmp/PKIHeader.cs b/Crypto/src/asn1/cmp/PKIHeader.cs
new file mode 100644
index 000000000..e758e9f16
--- /dev/null
+++ b/Crypto/src/asn1/cmp/PKIHeader.cs
@@ -0,0 +1,237 @@
+using System;
+
+using Org.BouncyCastle.Asn1.X509;
+
+namespace Org.BouncyCastle.Asn1.Cmp
+{
+ public class PkiHeader
+ : Asn1Encodable
+ {
+ /**
+ * Value for a "null" recipient or sender.
+ */
+ public static readonly GeneralName NULL_NAME = new GeneralName(X509Name.GetInstance(new DerSequence()));
+
+ public static readonly int CMP_1999 = 1;
+ public static readonly int CMP_2000 = 2;
+
+ private readonly DerInteger pvno;
+ private readonly GeneralName sender;
+ private readonly GeneralName recipient;
+ private readonly DerGeneralizedTime messageTime;
+ private readonly AlgorithmIdentifier protectionAlg;
+ private readonly Asn1OctetString senderKID; // KeyIdentifier
+ private readonly Asn1OctetString recipKID; // KeyIdentifier
+ private readonly Asn1OctetString transactionID;
+ private readonly Asn1OctetString senderNonce;
+ private readonly Asn1OctetString recipNonce;
+ private readonly PkiFreeText freeText;
+ private readonly Asn1Sequence generalInfo;
+
+ private PkiHeader(Asn1Sequence seq)
+ {
+ pvno = DerInteger.GetInstance(seq[0]);
+ sender = GeneralName.GetInstance(seq[1]);
+ recipient = GeneralName.GetInstance(seq[2]);
+
+ for (int pos = 3; pos < seq.Count; ++pos)
+ {
+ Asn1TaggedObject tObj = (Asn1TaggedObject)seq[pos];
+
+ switch (tObj.TagNo)
+ {
+ case 0:
+ messageTime = DerGeneralizedTime.GetInstance(tObj, true);
+ break;
+ case 1:
+ protectionAlg = AlgorithmIdentifier.GetInstance(tObj, true);
+ break;
+ case 2:
+ senderKID = Asn1OctetString.GetInstance(tObj, true);
+ break;
+ case 3:
+ recipKID = Asn1OctetString.GetInstance(tObj, true);
+ break;
+ case 4:
+ transactionID = Asn1OctetString.GetInstance(tObj, true);
+ break;
+ case 5:
+ senderNonce = Asn1OctetString.GetInstance(tObj, true);
+ break;
+ case 6:
+ recipNonce = Asn1OctetString.GetInstance(tObj, true);
+ break;
+ case 7:
+ freeText = PkiFreeText.GetInstance(tObj, true);
+ break;
+ case 8:
+ generalInfo = Asn1Sequence.GetInstance(tObj, true);
+ break;
+ default:
+ throw new ArgumentException("unknown tag number: " + tObj.TagNo, "seq");
+ }
+ }
+ }
+
+ public static PkiHeader GetInstance(object obj)
+ {
+ if (obj is PkiHeader)
+ return (PkiHeader)obj;
+
+ if (obj is Asn1Sequence)
+ return new PkiHeader((Asn1Sequence)obj);
+
+ throw new ArgumentException("Invalid object: " + obj.GetType().Name, "obj");
+ }
+
+ public PkiHeader(
+ int pvno,
+ GeneralName sender,
+ GeneralName recipient)
+ : this(new DerInteger(pvno), sender, recipient)
+ {
+ }
+
+ private PkiHeader(
+ DerInteger pvno,
+ GeneralName sender,
+ GeneralName recipient)
+ {
+ this.pvno = pvno;
+ this.sender = sender;
+ this.recipient = recipient;
+ }
+
+ public virtual DerInteger Pvno
+ {
+ get { return pvno; }
+ }
+
+ public virtual GeneralName Sender
+ {
+ get { return sender; }
+ }
+
+ public virtual GeneralName Recipient
+ {
+ get { return recipient; }
+ }
+
+ public virtual DerGeneralizedTime MessageTime
+ {
+ get { return messageTime; }
+ }
+
+ public virtual AlgorithmIdentifier ProtectionAlg
+ {
+ get { return protectionAlg; }
+ }
+
+ public virtual Asn1OctetString SenderKID
+ {
+ get { return senderKID; }
+ }
+
+ public virtual Asn1OctetString RecipKID
+ {
+ get { return recipKID; }
+ }
+
+ public virtual Asn1OctetString TransactionID
+ {
+ get { return transactionID; }
+ }
+
+ public virtual Asn1OctetString SenderNonce
+ {
+ get { return senderNonce; }
+ }
+
+ public virtual Asn1OctetString RecipNonce
+ {
+ get { return recipNonce; }
+ }
+
+ public virtual PkiFreeText FreeText
+ {
+ get { return freeText; }
+ }
+
+ public virtual InfoTypeAndValue[] GetGeneralInfo()
+ {
+ if (generalInfo == null)
+ {
+ return null;
+ }
+ InfoTypeAndValue[] results = new InfoTypeAndValue[generalInfo.Count];
+ for (int i = 0; i < results.Length; i++)
+ {
+ results[i] = InfoTypeAndValue.GetInstance(generalInfo[i]);
+ }
+ return results;
+ }
+
+ /**
+ * <pre>
+ * PkiHeader ::= SEQUENCE {
+ * pvno INTEGER { cmp1999(1), cmp2000(2) },
+ * sender GeneralName,
+ * -- identifies the sender
+ * recipient GeneralName,
+ * -- identifies the intended recipient
+ * messageTime [0] GeneralizedTime OPTIONAL,
+ * -- time of production of this message (used when sender
+ * -- believes that the transport will be "suitable"; i.e.,
+ * -- that the time will still be meaningful upon receipt)
+ * protectionAlg [1] AlgorithmIdentifier OPTIONAL,
+ * -- algorithm used for calculation of protection bits
+ * senderKID [2] KeyIdentifier OPTIONAL,
+ * recipKID [3] KeyIdentifier OPTIONAL,
+ * -- to identify specific keys used for protection
+ * transactionID [4] OCTET STRING OPTIONAL,
+ * -- identifies the transaction; i.e., this will be the same in
+ * -- corresponding request, response, certConf, and PKIConf
+ * -- messages
+ * senderNonce [5] OCTET STRING OPTIONAL,
+ * recipNonce [6] OCTET STRING OPTIONAL,
+ * -- nonces used to provide replay protection, senderNonce
+ * -- is inserted by the creator of this message; recipNonce
+ * -- is a nonce previously inserted in a related message by
+ * -- the intended recipient of this message
+ * freeText [7] PKIFreeText OPTIONAL,
+ * -- this may be used to indicate context-specific instructions
+ * -- (this field is intended for human consumption)
+ * generalInfo [8] SEQUENCE SIZE (1..MAX) OF
+ * InfoTypeAndValue OPTIONAL
+ * -- this may be used to convey context-specific information
+ * -- (this field not primarily intended for human consumption)
+ * }
+ * </pre>
+ * @return a basic ASN.1 object representation.
+ */
+ public override Asn1Object ToAsn1Object()
+ {
+ Asn1EncodableVector v = new Asn1EncodableVector(pvno, sender, recipient);
+
+ AddOptional(v, 0, messageTime);
+ AddOptional(v, 1, protectionAlg);
+ AddOptional(v, 2, senderKID);
+ AddOptional(v, 3, recipKID);
+ AddOptional(v, 4, transactionID);
+ AddOptional(v, 5, senderNonce);
+ AddOptional(v, 6, recipNonce);
+ AddOptional(v, 7, freeText);
+ AddOptional(v, 8, generalInfo);
+
+ return new DerSequence(v);
+ }
+
+ private static void AddOptional(Asn1EncodableVector v, int tagNo, Asn1Encodable obj)
+ {
+ if (obj != null)
+ {
+ v.Add(new DerTaggedObject(true, tagNo, obj));
+ }
+ }
+ }
+}
diff --git a/Crypto/src/asn1/cmp/PKIHeaderBuilder.cs b/Crypto/src/asn1/cmp/PKIHeaderBuilder.cs
new file mode 100644
index 000000000..00073c062
--- /dev/null
+++ b/Crypto/src/asn1/cmp/PKIHeaderBuilder.cs
@@ -0,0 +1,223 @@
+using System;
+
+using Org.BouncyCastle.Asn1.X509;
+
+namespace Org.BouncyCastle.Asn1.Cmp
+{
+ public class PkiHeaderBuilder
+ {
+ private DerInteger pvno;
+ private GeneralName sender;
+ private GeneralName recipient;
+ private DerGeneralizedTime messageTime;
+ private AlgorithmIdentifier protectionAlg;
+ private Asn1OctetString senderKID; // KeyIdentifier
+ private Asn1OctetString recipKID; // KeyIdentifier
+ private Asn1OctetString transactionID;
+ private Asn1OctetString senderNonce;
+ private Asn1OctetString recipNonce;
+ private PkiFreeText freeText;
+ private Asn1Sequence generalInfo;
+
+ public PkiHeaderBuilder(
+ int pvno,
+ GeneralName sender,
+ GeneralName recipient)
+ : this(new DerInteger(pvno), sender, recipient)
+ {
+ }
+
+ private PkiHeaderBuilder(
+ DerInteger pvno,
+ GeneralName sender,
+ GeneralName recipient)
+ {
+ this.pvno = pvno;
+ this.sender = sender;
+ this.recipient = recipient;
+ }
+
+ public virtual PkiHeaderBuilder SetMessageTime(DerGeneralizedTime time)
+ {
+ messageTime = time;
+ return this;
+ }
+
+ public virtual PkiHeaderBuilder SetProtectionAlg(AlgorithmIdentifier aid)
+ {
+ protectionAlg = aid;
+ return this;
+ }
+
+ public virtual PkiHeaderBuilder SetSenderKID(byte[] kid)
+ {
+ return SetSenderKID(kid == null ? null : new DerOctetString(kid));
+ }
+
+ public virtual PkiHeaderBuilder SetSenderKID(Asn1OctetString kid)
+ {
+ senderKID = kid;
+ return this;
+ }
+
+ public virtual PkiHeaderBuilder SetRecipKID(byte[] kid)
+ {
+ return SetRecipKID(kid == null ? null : new DerOctetString(kid));
+ }
+
+ public virtual PkiHeaderBuilder SetRecipKID(DerOctetString kid)
+ {
+ recipKID = kid;
+ return this;
+ }
+
+ public virtual PkiHeaderBuilder SetTransactionID(byte[] tid)
+ {
+ return SetTransactionID(tid == null ? null : new DerOctetString(tid));
+ }
+
+ public virtual PkiHeaderBuilder SetTransactionID(Asn1OctetString tid)
+ {
+ transactionID = tid;
+ return this;
+ }
+
+ public virtual PkiHeaderBuilder SetSenderNonce(byte[] nonce)
+ {
+ return SetSenderNonce(nonce == null ? null : new DerOctetString(nonce));
+ }
+
+ public virtual PkiHeaderBuilder SetSenderNonce(Asn1OctetString nonce)
+ {
+ senderNonce = nonce;
+ return this;
+ }
+
+ public virtual PkiHeaderBuilder SetRecipNonce(byte[] nonce)
+ {
+ return SetRecipNonce(nonce == null ? null : new DerOctetString(nonce));
+ }
+
+ public virtual PkiHeaderBuilder SetRecipNonce(Asn1OctetString nonce)
+ {
+ recipNonce = nonce;
+ return this;
+ }
+
+ public virtual PkiHeaderBuilder SetFreeText(PkiFreeText text)
+ {
+ freeText = text;
+ return this;
+ }
+
+ public virtual PkiHeaderBuilder SetGeneralInfo(InfoTypeAndValue genInfo)
+ {
+ return SetGeneralInfo(MakeGeneralInfoSeq(genInfo));
+ }
+
+ public virtual PkiHeaderBuilder SetGeneralInfo(InfoTypeAndValue[] genInfos)
+ {
+ return SetGeneralInfo(MakeGeneralInfoSeq(genInfos));
+ }
+
+ public virtual PkiHeaderBuilder SetGeneralInfo(Asn1Sequence seqOfInfoTypeAndValue)
+ {
+ generalInfo = seqOfInfoTypeAndValue;
+ return this;
+ }
+
+ private static Asn1Sequence MakeGeneralInfoSeq(
+ InfoTypeAndValue generalInfo)
+ {
+ return new DerSequence(generalInfo);
+ }
+
+ private static Asn1Sequence MakeGeneralInfoSeq(
+ InfoTypeAndValue[] generalInfos)
+ {
+ Asn1Sequence genInfoSeq = null;
+ if (generalInfos != null)
+ {
+ Asn1EncodableVector v = new Asn1EncodableVector();
+ for (int i = 0; i < generalInfos.Length; ++i)
+ {
+ v.Add(generalInfos[i]);
+ }
+ genInfoSeq = new DerSequence(v);
+ }
+ return genInfoSeq;
+ }
+
+ /**
+ * <pre>
+ * PKIHeader ::= SEQUENCE {
+ * pvno INTEGER { cmp1999(1), cmp2000(2) },
+ * sender GeneralName,
+ * -- identifies the sender
+ * recipient GeneralName,
+ * -- identifies the intended recipient
+ * messageTime [0] GeneralizedTime OPTIONAL,
+ * -- time of production of this message (used when sender
+ * -- believes that the transport will be "suitable"; i.e.,
+ * -- that the time will still be meaningful upon receipt)
+ * protectionAlg [1] AlgorithmIdentifier OPTIONAL,
+ * -- algorithm used for calculation of protection bits
+ * senderKID [2] KeyIdentifier OPTIONAL,
+ * recipKID [3] KeyIdentifier OPTIONAL,
+ * -- to identify specific keys used for protection
+ * transactionID [4] OCTET STRING OPTIONAL,
+ * -- identifies the transaction; i.e., this will be the same in
+ * -- corresponding request, response, certConf, and PKIConf
+ * -- messages
+ * senderNonce [5] OCTET STRING OPTIONAL,
+ * recipNonce [6] OCTET STRING OPTIONAL,
+ * -- nonces used to provide replay protection, senderNonce
+ * -- is inserted by the creator of this message; recipNonce
+ * -- is a nonce previously inserted in a related message by
+ * -- the intended recipient of this message
+ * freeText [7] PKIFreeText OPTIONAL,
+ * -- this may be used to indicate context-specific instructions
+ * -- (this field is intended for human consumption)
+ * generalInfo [8] SEQUENCE SIZE (1..MAX) OF
+ * InfoTypeAndValue OPTIONAL
+ * -- this may be used to convey context-specific information
+ * -- (this field not primarily intended for human consumption)
+ * }
+ * </pre>
+ * @return a basic ASN.1 object representation.
+ */
+ public virtual PkiHeader Build()
+ {
+ Asn1EncodableVector v = new Asn1EncodableVector(pvno, sender, recipient);
+ AddOptional(v, 0, messageTime);
+ AddOptional(v, 1, protectionAlg);
+ AddOptional(v, 2, senderKID);
+ AddOptional(v, 3, recipKID);
+ AddOptional(v, 4, transactionID);
+ AddOptional(v, 5, senderNonce);
+ AddOptional(v, 6, recipNonce);
+ AddOptional(v, 7, freeText);
+ AddOptional(v, 8, generalInfo);
+
+ messageTime = null;
+ protectionAlg = null;
+ senderKID = null;
+ recipKID = null;
+ transactionID = null;
+ senderNonce = null;
+ recipNonce = null;
+ freeText = null;
+ generalInfo = null;
+
+ return PkiHeader.GetInstance(new DerSequence(v));
+ }
+
+ private void AddOptional(Asn1EncodableVector v, int tagNo, Asn1Encodable obj)
+ {
+ if (obj != null)
+ {
+ v.Add(new DerTaggedObject(true, tagNo, obj));
+ }
+ }
+ }
+}
diff --git a/Crypto/src/asn1/cmp/PKIMessage.cs b/Crypto/src/asn1/cmp/PKIMessage.cs
new file mode 100644
index 000000000..086a2d938
--- /dev/null
+++ b/Crypto/src/asn1/cmp/PKIMessage.cs
@@ -0,0 +1,140 @@
+using System;
+
+namespace Org.BouncyCastle.Asn1.Cmp
+{
+ public class PkiMessage
+ : Asn1Encodable
+ {
+ private readonly PkiHeader header;
+ private readonly PkiBody body;
+ private readonly DerBitString protection;
+ private readonly Asn1Sequence extraCerts;
+
+ private PkiMessage(Asn1Sequence seq)
+ {
+ header = PkiHeader.GetInstance(seq[0]);
+ body = PkiBody.GetInstance(seq[1]);
+
+ for (int pos = 2; pos < seq.Count; ++pos)
+ {
+ Asn1TaggedObject tObj = (Asn1TaggedObject)seq[pos].ToAsn1Object();
+
+ if (tObj.TagNo == 0)
+ {
+ protection = DerBitString.GetInstance(tObj, true);
+ }
+ else
+ {
+ extraCerts = Asn1Sequence.GetInstance(tObj, true);
+ }
+ }
+ }
+
+ public static PkiMessage GetInstance(object obj)
+ {
+ if (obj is PkiMessage)
+ return (PkiMessage)obj;
+
+ if (obj != null)
+ return new PkiMessage(Asn1Sequence.GetInstance(obj));
+
+ return null;
+ }
+
+ /**
+ * Creates a new PkiMessage.
+ *
+ * @param header message header
+ * @param body message body
+ * @param protection message protection (may be null)
+ * @param extraCerts extra certificates (may be null)
+ */
+ public PkiMessage(
+ PkiHeader header,
+ PkiBody body,
+ DerBitString protection,
+ CmpCertificate[] extraCerts)
+ {
+ this.header = header;
+ this.body = body;
+ this.protection = protection;
+ if (extraCerts != null)
+ {
+ this.extraCerts = new DerSequence(extraCerts);
+ }
+ }
+
+ public PkiMessage(
+ PkiHeader header,
+ PkiBody body,
+ DerBitString protection)
+ : this(header, body, protection, null)
+ {
+ }
+
+ public PkiMessage(
+ PkiHeader header,
+ PkiBody body)
+ : this(header, body, null, null)
+ {
+ }
+
+ public virtual PkiHeader Header
+ {
+ get { return header; }
+ }
+
+ public virtual PkiBody Body
+ {
+ get { return body; }
+ }
+
+ public virtual DerBitString Protection
+ {
+ get { return protection; }
+ }
+
+ public virtual CmpCertificate[] GetExtraCerts()
+ {
+ if (extraCerts == null)
+ return null;
+
+ CmpCertificate[] results = new CmpCertificate[extraCerts.Count];
+ for (int i = 0; i < results.Length; ++i)
+ {
+ results[i] = CmpCertificate.GetInstance(extraCerts[i]);
+ }
+ return results;
+ }
+
+ /**
+ * <pre>
+ * PkiMessage ::= SEQUENCE {
+ * header PKIHeader,
+ * body PKIBody,
+ * protection [0] PKIProtection OPTIONAL,
+ * extraCerts [1] SEQUENCE SIZE (1..MAX) OF CMPCertificate
+ * OPTIONAL
+ * }
+ * </pre>
+ * @return a basic ASN.1 object representation.
+ */
+ public override Asn1Object ToAsn1Object()
+ {
+ Asn1EncodableVector v = new Asn1EncodableVector(header, body);
+
+ AddOptional(v, 0, protection);
+ AddOptional(v, 1, extraCerts);
+
+ return new DerSequence(v);
+ }
+
+ private static void AddOptional(Asn1EncodableVector v, int tagNo, Asn1Encodable obj)
+ {
+ if (obj != null)
+ {
+ v.Add(new DerTaggedObject(true, tagNo, obj));
+ }
+ }
+ }
+}
diff --git a/Crypto/src/asn1/cmp/PKIMessages.cs b/Crypto/src/asn1/cmp/PKIMessages.cs
new file mode 100644
index 000000000..ddabdf4ae
--- /dev/null
+++ b/Crypto/src/asn1/cmp/PKIMessages.cs
@@ -0,0 +1,52 @@
+using System;
+
+namespace Org.BouncyCastle.Asn1.Cmp
+{
+ public class PkiMessages
+ : Asn1Encodable
+ {
+ private Asn1Sequence content;
+
+ private PkiMessages(Asn1Sequence seq)
+ {
+ content = seq;
+ }
+
+ public static PkiMessages GetInstance(object obj)
+ {
+ if (obj is PkiMessages)
+ return (PkiMessages)obj;
+
+ if (obj is Asn1Sequence)
+ return new PkiMessages((Asn1Sequence)obj);
+
+ throw new ArgumentException("Invalid object: " + obj.GetType().Name, "obj");
+ }
+
+ public PkiMessages(params PkiMessage[] msgs)
+ {
+ content = new DerSequence(msgs);
+ }
+
+ public virtual PkiMessage[] ToPkiMessageArray()
+ {
+ PkiMessage[] result = new PkiMessage[content.Count];
+ for (int i = 0; i != result.Length; ++i)
+ {
+ result[i] = PkiMessage.GetInstance(content[i]);
+ }
+ return result;
+ }
+
+ /**
+ * <pre>
+ * PkiMessages ::= SEQUENCE SIZE (1..MAX) OF PkiMessage
+ * </pre>
+ * @return a basic ASN.1 object representation.
+ */
+ public override Asn1Object ToAsn1Object()
+ {
+ return content;
+ }
+ }
+}
diff --git a/Crypto/src/asn1/cmp/PKIStatus.cs b/Crypto/src/asn1/cmp/PKIStatus.cs
new file mode 100644
index 000000000..b03dd3d62
--- /dev/null
+++ b/Crypto/src/asn1/cmp/PKIStatus.cs
@@ -0,0 +1,62 @@
+using System;
+
+using Org.BouncyCastle.Math;
+
+namespace Org.BouncyCastle.Asn1.Cmp
+{
+ public enum PkiStatus
+ {
+ Granted = 0,
+ GrantedWithMods = 1,
+ Rejection = 2,
+ Waiting = 3,
+ RevocationWarning = 4,
+ RevocationNotification = 5,
+ KeyUpdateWarning = 6,
+ }
+
+ public class PkiStatusEncodable
+ : Asn1Encodable
+ {
+ public static readonly PkiStatusEncodable granted = new PkiStatusEncodable(PkiStatus.Granted);
+ public static readonly PkiStatusEncodable grantedWithMods = new PkiStatusEncodable(PkiStatus.GrantedWithMods);
+ public static readonly PkiStatusEncodable rejection = new PkiStatusEncodable(PkiStatus.Rejection);
+ public static readonly PkiStatusEncodable waiting = new PkiStatusEncodable(PkiStatus.Waiting);
+ public static readonly PkiStatusEncodable revocationWarning = new PkiStatusEncodable(PkiStatus.RevocationWarning);
+ public static readonly PkiStatusEncodable revocationNotification = new PkiStatusEncodable(PkiStatus.RevocationNotification);
+ public static readonly PkiStatusEncodable keyUpdateWaiting = new PkiStatusEncodable(PkiStatus.KeyUpdateWarning);
+
+ private readonly DerInteger status;
+
+ private PkiStatusEncodable(PkiStatus status)
+ : this(new DerInteger((int)status))
+ {
+ }
+
+ private PkiStatusEncodable(DerInteger status)
+ {
+ this.status = status;
+ }
+
+ public static PkiStatusEncodable GetInstance(object obj)
+ {
+ if (obj is PkiStatusEncodable)
+ return (PkiStatusEncodable)obj;
+
+ if (obj is DerInteger)
+ return new PkiStatusEncodable((DerInteger)obj);
+
+ throw new ArgumentException("Invalid object: " + obj.GetType().Name, "obj");
+ }
+
+ public virtual BigInteger Value
+ {
+ get { return status.Value; }
+ }
+
+ public override Asn1Object ToAsn1Object()
+ {
+ return status;
+ }
+ }
+}
diff --git a/Crypto/src/asn1/cmp/PKIStatusInfo.cs b/Crypto/src/asn1/cmp/PKIStatusInfo.cs
new file mode 100644
index 000000000..2463e0081
--- /dev/null
+++ b/Crypto/src/asn1/cmp/PKIStatusInfo.cs
@@ -0,0 +1,165 @@
+using System;
+
+using Org.BouncyCastle.Math;
+
+namespace Org.BouncyCastle.Asn1.Cmp
+{
+ public class PkiStatusInfo
+ : Asn1Encodable
+ {
+ DerInteger status;
+ PkiFreeText statusString;
+ DerBitString failInfo;
+
+ public static PkiStatusInfo GetInstance(
+ Asn1TaggedObject obj,
+ bool isExplicit)
+ {
+ return GetInstance(Asn1Sequence.GetInstance(obj, isExplicit));
+ }
+
+ public static PkiStatusInfo GetInstance(
+ object obj)
+ {
+ if (obj is PkiStatusInfo)
+ {
+ return (PkiStatusInfo)obj;
+ }
+ else if (obj is Asn1Sequence)
+ {
+ return new PkiStatusInfo((Asn1Sequence)obj);
+ }
+
+ throw new ArgumentException("Unknown object in factory: " + obj.GetType().Name, "obj");
+ }
+
+ public PkiStatusInfo(
+ Asn1Sequence seq)
+ {
+ this.status = DerInteger.GetInstance(seq[0]);
+
+ this.statusString = null;
+ this.failInfo = null;
+
+ if (seq.Count > 2)
+ {
+ this.statusString = PkiFreeText.GetInstance(seq[1]);
+ this.failInfo = DerBitString.GetInstance(seq[2]);
+ }
+ else if (seq.Count > 1)
+ {
+ object obj = seq[1];
+ if (obj is DerBitString)
+ {
+ this.failInfo = DerBitString.GetInstance(obj);
+ }
+ else
+ {
+ this.statusString = PkiFreeText.GetInstance(obj);
+ }
+ }
+ }
+
+ /**
+ * @param status
+ */
+ public PkiStatusInfo(int status)
+ {
+ this.status = new DerInteger(status);
+ }
+
+ /**
+ * @param status
+ * @param statusString
+ */
+ public PkiStatusInfo(
+ int status,
+ PkiFreeText statusString)
+ {
+ this.status = new DerInteger(status);
+ this.statusString = statusString;
+ }
+
+ public PkiStatusInfo(
+ int status,
+ PkiFreeText statusString,
+ PkiFailureInfo failInfo)
+ {
+ this.status = new DerInteger(status);
+ this.statusString = statusString;
+ this.failInfo = failInfo;
+ }
+
+ public BigInteger Status
+ {
+ get
+ {
+ return status.Value;
+ }
+ }
+
+ public PkiFreeText StatusString
+ {
+ get
+ {
+ return statusString;
+ }
+ }
+
+ public DerBitString FailInfo
+ {
+ get
+ {
+ return failInfo;
+ }
+ }
+
+ /**
+ * <pre>
+ * PkiStatusInfo ::= SEQUENCE {
+ * status PKIStatus, (INTEGER)
+ * statusString PkiFreeText OPTIONAL,
+ * failInfo PkiFailureInfo OPTIONAL (BIT STRING)
+ * }
+ *
+ * PKIStatus:
+ * granted (0), -- you got exactly what you asked for
+ * grantedWithMods (1), -- you got something like what you asked for
+ * rejection (2), -- you don't get it, more information elsewhere in the message
+ * waiting (3), -- the request body part has not yet been processed, expect to hear more later
+ * revocationWarning (4), -- this message contains a warning that a revocation is imminent
+ * revocationNotification (5), -- notification that a revocation has occurred
+ * keyUpdateWarning (6) -- update already done for the oldCertId specified in CertReqMsg
+ *
+ * PkiFailureInfo:
+ * badAlg (0), -- unrecognized or unsupported Algorithm Identifier
+ * badMessageCheck (1), -- integrity check failed (e.g., signature did not verify)
+ * badRequest (2), -- transaction not permitted or supported
+ * badTime (3), -- messageTime was not sufficiently close to the system time, as defined by local policy
+ * badCertId (4), -- no certificate could be found matching the provided criteria
+ * badDataFormat (5), -- the data submitted has the wrong format
+ * wrongAuthority (6), -- the authority indicated in the request is different from the one creating the response token
+ * incorrectData (7), -- the requester's data is incorrect (for notary services)
+ * missingTimeStamp (8), -- when the timestamp is missing but should be there (by policy)
+ * badPOP (9) -- the proof-of-possession failed
+ *
+ * </pre>
+ */
+ public override Asn1Object ToAsn1Object()
+ {
+ Asn1EncodableVector v = new Asn1EncodableVector(status);
+
+ if (statusString != null)
+ {
+ v.Add(statusString);
+ }
+
+ if (failInfo!= null)
+ {
+ v.Add(failInfo);
+ }
+
+ return new DerSequence(v);
+ }
+ }
+}
diff --git a/Crypto/src/asn1/cmp/PbmParameter.cs b/Crypto/src/asn1/cmp/PbmParameter.cs
new file mode 100644
index 000000000..59b1bd7bb
--- /dev/null
+++ b/Crypto/src/asn1/cmp/PbmParameter.cs
@@ -0,0 +1,100 @@
+using System;
+
+using Org.BouncyCastle.Asn1.X509;
+
+namespace Org.BouncyCastle.Asn1.Cmp
+{
+ public class PbmParameter
+ : Asn1Encodable
+ {
+ private Asn1OctetString salt;
+ private AlgorithmIdentifier owf;
+ private DerInteger iterationCount;
+ private AlgorithmIdentifier mac;
+
+ private PbmParameter(Asn1Sequence seq)
+ {
+ salt = Asn1OctetString.GetInstance(seq[0]);
+ owf = AlgorithmIdentifier.GetInstance(seq[1]);
+ iterationCount = DerInteger.GetInstance(seq[2]);
+ mac = AlgorithmIdentifier.GetInstance(seq[3]);
+ }
+
+ public static PbmParameter GetInstance(object obj)
+ {
+ if (obj is PbmParameter)
+ return (PbmParameter)obj;
+
+ if (obj is Asn1Sequence)
+ return new PbmParameter((Asn1Sequence)obj);
+
+ throw new ArgumentException("Invalid object: " + obj.GetType().Name, "obj");
+ }
+
+ public PbmParameter(
+ byte[] salt,
+ AlgorithmIdentifier owf,
+ int iterationCount,
+ AlgorithmIdentifier mac)
+ : this(new DerOctetString(salt), owf, new DerInteger(iterationCount), mac)
+ {
+ }
+
+ public PbmParameter(
+ Asn1OctetString salt,
+ AlgorithmIdentifier owf,
+ DerInteger iterationCount,
+ AlgorithmIdentifier mac)
+ {
+ this.salt = salt;
+ this.owf = owf;
+ this.iterationCount = iterationCount;
+ this.mac = mac;
+ }
+
+ public virtual Asn1OctetString Salt
+ {
+ get { return salt; }
+ }
+
+ public virtual AlgorithmIdentifier Owf
+ {
+ get { return owf; }
+ }
+
+ public virtual DerInteger IterationCount
+ {
+ get { return iterationCount; }
+ }
+
+ public virtual AlgorithmIdentifier Mac
+ {
+ get { return mac; }
+ }
+
+ /**
+ * <pre>
+ * PbmParameter ::= SEQUENCE {
+ * salt OCTET STRING,
+ * -- note: implementations MAY wish to limit acceptable sizes
+ * -- of this string to values appropriate for their environment
+ * -- in order to reduce the risk of denial-of-service attacks
+ * owf AlgorithmIdentifier,
+ * -- AlgId for a One-Way Function (SHA-1 recommended)
+ * iterationCount INTEGER,
+ * -- number of times the OWF is applied
+ * -- note: implementations MAY wish to limit acceptable sizes
+ * -- of this integer to values appropriate for their environment
+ * -- in order to reduce the risk of denial-of-service attacks
+ * mac AlgorithmIdentifier
+ * -- the MAC AlgId (e.g., DES-MAC, Triple-DES-MAC [PKCS11],
+ * } -- or HMAC [RFC2104, RFC2202])
+ * </pre>
+ * @return a basic ASN.1 object representation.
+ */
+ public override Asn1Object ToAsn1Object()
+ {
+ return new DerSequence(salt, owf, iterationCount, mac);
+ }
+ }
+}
diff --git a/Crypto/src/asn1/cmp/PollRepContent.cs b/Crypto/src/asn1/cmp/PollRepContent.cs
new file mode 100644
index 000000000..4045ac7ed
--- /dev/null
+++ b/Crypto/src/asn1/cmp/PollRepContent.cs
@@ -0,0 +1,66 @@
+using System;
+
+namespace Org.BouncyCastle.Asn1.Cmp
+{
+ public class PollRepContent
+ : Asn1Encodable
+ {
+ private readonly DerInteger certReqId;
+ private readonly DerInteger checkAfter;
+ private readonly PkiFreeText reason;
+
+ private PollRepContent(Asn1Sequence seq)
+ {
+ certReqId = DerInteger.GetInstance(seq[0]);
+ checkAfter = DerInteger.GetInstance(seq[1]);
+
+ if (seq.Count > 2)
+ {
+ reason = PkiFreeText.GetInstance(seq[2]);
+ }
+ }
+
+ public static PollRepContent GetInstance(object obj)
+ {
+ if (obj is PollRepContent)
+ return (PollRepContent)obj;
+
+ if (obj is Asn1Sequence)
+ return new PollRepContent((Asn1Sequence)obj);
+
+ throw new ArgumentException("Invalid object: " + obj.GetType().Name, "obj");
+ }
+
+ public virtual DerInteger CertReqID
+ {
+ get { return certReqId; }
+ }
+
+ public virtual DerInteger CheckAfter
+ {
+ get { return checkAfter; }
+ }
+
+ public virtual PkiFreeText Reason
+ {
+ get { return reason; }
+ }
+
+ /**
+ * <pre>
+ * PollRepContent ::= SEQUENCE OF SEQUENCE {
+ * certReqId INTEGER,
+ * checkAfter INTEGER, -- time in seconds
+ * reason PKIFreeText OPTIONAL
+ * }
+ * </pre>
+ * @return a basic ASN.1 object representation.
+ */
+ public override Asn1Object ToAsn1Object()
+ {
+ Asn1EncodableVector v = new Asn1EncodableVector(certReqId, checkAfter);
+ v.AddOptional(reason);
+ return new DerSequence(v);
+ }
+ }
+}
diff --git a/Crypto/src/asn1/cmp/PollReqContent.cs b/Crypto/src/asn1/cmp/PollReqContent.cs
new file mode 100644
index 000000000..ca2164151
--- /dev/null
+++ b/Crypto/src/asn1/cmp/PollReqContent.cs
@@ -0,0 +1,59 @@
+using System;
+
+namespace Org.BouncyCastle.Asn1.Cmp
+{
+ public class PollReqContent
+ : Asn1Encodable
+ {
+ private readonly Asn1Sequence content;
+
+ private PollReqContent(Asn1Sequence seq)
+ {
+ content = seq;
+ }
+
+ public static PollReqContent GetInstance(object obj)
+ {
+ if (obj is PollReqContent)
+ return (PollReqContent)obj;
+
+ if (obj is Asn1Sequence)
+ return new PollReqContent((Asn1Sequence)obj);
+
+ throw new ArgumentException("Invalid object: " + obj.GetType().Name, "obj");
+ }
+
+ public virtual DerInteger[][] GetCertReqIDs()
+ {
+ DerInteger[][] result = new DerInteger[content.Count][];
+ for (int i = 0; i != result.Length; ++i)
+ {
+ result[i] = SequenceToDerIntegerArray((Asn1Sequence)content[i]);
+ }
+ return result;
+ }
+
+ private static DerInteger[] SequenceToDerIntegerArray(Asn1Sequence seq)
+ {
+ DerInteger[] result = new DerInteger[seq.Count];
+ for (int i = 0; i != result.Length; ++i)
+ {
+ result[i] = DerInteger.GetInstance(seq[i]);
+ }
+ return result;
+ }
+
+ /**
+ * <pre>
+ * PollReqContent ::= SEQUENCE OF SEQUENCE {
+ * certReqId INTEGER
+ * }
+ * </pre>
+ * @return a basic ASN.1 object representation.
+ */
+ public override Asn1Object ToAsn1Object()
+ {
+ return content;
+ }
+ }
+}
diff --git a/Crypto/src/asn1/cmp/PopoDecKeyChallContent.cs b/Crypto/src/asn1/cmp/PopoDecKeyChallContent.cs
new file mode 100644
index 000000000..20b173b85
--- /dev/null
+++ b/Crypto/src/asn1/cmp/PopoDecKeyChallContent.cs
@@ -0,0 +1,47 @@
+using System;
+
+namespace Org.BouncyCastle.Asn1.Cmp
+{
+ public class PopoDecKeyChallContent
+ : Asn1Encodable
+ {
+ private readonly Asn1Sequence content;
+
+ private PopoDecKeyChallContent(Asn1Sequence seq)
+ {
+ content = seq;
+ }
+
+ public static PopoDecKeyChallContent GetInstance(object obj)
+ {
+ if (obj is PopoDecKeyChallContent)
+ return (PopoDecKeyChallContent)obj;
+
+ if (obj is Asn1Sequence)
+ return new PopoDecKeyChallContent((Asn1Sequence)obj);
+
+ throw new ArgumentException("Invalid object: " + obj.GetType().Name, "obj");
+ }
+
+ public virtual Challenge[] ToChallengeArray()
+ {
+ Challenge[] result = new Challenge[content.Count];
+ for (int i = 0; i != result.Length; ++i)
+ {
+ result[i] = Challenge.GetInstance(content[i]);
+ }
+ return result;
+ }
+
+ /**
+ * <pre>
+ * PopoDecKeyChallContent ::= SEQUENCE OF Challenge
+ * </pre>
+ * @return a basic ASN.1 object representation.
+ */
+ public override Asn1Object ToAsn1Object()
+ {
+ return content;
+ }
+ }
+}
diff --git a/Crypto/src/asn1/cmp/PopoDecKeyRespContent.cs b/Crypto/src/asn1/cmp/PopoDecKeyRespContent.cs
new file mode 100644
index 000000000..8c322e4ec
--- /dev/null
+++ b/Crypto/src/asn1/cmp/PopoDecKeyRespContent.cs
@@ -0,0 +1,47 @@
+using System;
+
+namespace Org.BouncyCastle.Asn1.Cmp
+{
+ public class PopoDecKeyRespContent
+ : Asn1Encodable
+ {
+ private readonly Asn1Sequence content;
+
+ private PopoDecKeyRespContent(Asn1Sequence seq)
+ {
+ content = seq;
+ }
+
+ public static PopoDecKeyRespContent GetInstance(object obj)
+ {
+ if (obj is PopoDecKeyRespContent)
+ return (PopoDecKeyRespContent)obj;
+
+ if (obj is Asn1Sequence)
+ return new PopoDecKeyRespContent((Asn1Sequence)obj);
+
+ throw new ArgumentException("Invalid object: " + obj.GetType().Name, "obj");
+ }
+
+ public virtual DerInteger[] ToDerIntegerArray()
+ {
+ DerInteger[] result = new DerInteger[content.Count];
+ for (int i = 0; i != result.Length; ++i)
+ {
+ result[i] = DerInteger.GetInstance(content[i]);
+ }
+ return result;
+ }
+
+ /**
+ * <pre>
+ * PopoDecKeyRespContent ::= SEQUENCE OF INTEGER
+ * </pre>
+ * @return a basic ASN.1 object representation.
+ */
+ public override Asn1Object ToAsn1Object()
+ {
+ return content;
+ }
+ }
+}
diff --git a/Crypto/src/asn1/cmp/ProtectedPart.cs b/Crypto/src/asn1/cmp/ProtectedPart.cs
new file mode 100644
index 000000000..db6798fee
--- /dev/null
+++ b/Crypto/src/asn1/cmp/ProtectedPart.cs
@@ -0,0 +1,58 @@
+using System;
+
+namespace Org.BouncyCastle.Asn1.Cmp
+{
+ public class ProtectedPart
+ : Asn1Encodable
+ {
+ private readonly PkiHeader header;
+ private readonly PkiBody body;
+
+ private ProtectedPart(Asn1Sequence seq)
+ {
+ header = PkiHeader.GetInstance(seq[0]);
+ body = PkiBody.GetInstance(seq[1]);
+ }
+
+ public static ProtectedPart GetInstance(object obj)
+ {
+ if (obj is ProtectedPart)
+ return (ProtectedPart)obj;
+
+ if (obj is Asn1Sequence)
+ return new ProtectedPart((Asn1Sequence)obj);
+
+ throw new ArgumentException("Invalid object: " + obj.GetType().Name, "obj");
+ }
+
+ public ProtectedPart(PkiHeader header, PkiBody body)
+ {
+ this.header = header;
+ this.body = body;
+ }
+
+ public virtual PkiHeader Header
+ {
+ get { return header; }
+ }
+
+ public virtual PkiBody Body
+ {
+ get { return body; }
+ }
+
+ /**
+ * <pre>
+ * ProtectedPart ::= SEQUENCE {
+ * header PKIHeader,
+ * body PKIBody
+ * }
+ * </pre>
+ * @return a basic ASN.1 object representation.
+ */
+ public override Asn1Object ToAsn1Object()
+ {
+ return new DerSequence(header, body);
+ }
+ }
+}
diff --git a/Crypto/src/asn1/cmp/RevAnnContent.cs b/Crypto/src/asn1/cmp/RevAnnContent.cs
new file mode 100644
index 000000000..2c3bd5f77
--- /dev/null
+++ b/Crypto/src/asn1/cmp/RevAnnContent.cs
@@ -0,0 +1,86 @@
+using System;
+
+using Org.BouncyCastle.Asn1.Crmf;
+using Org.BouncyCastle.Asn1.X509;
+
+namespace Org.BouncyCastle.Asn1.Cmp
+{
+ public class RevAnnContent
+ : Asn1Encodable
+ {
+ private readonly PkiStatusEncodable status;
+ private readonly CertId certId;
+ private readonly DerGeneralizedTime willBeRevokedAt;
+ private readonly DerGeneralizedTime badSinceDate;
+ private readonly X509Extensions crlDetails;
+
+ private RevAnnContent(Asn1Sequence seq)
+ {
+ status = PkiStatusEncodable.GetInstance(seq[0]);
+ certId = CertId.GetInstance(seq[1]);
+ willBeRevokedAt = DerGeneralizedTime.GetInstance(seq[2]);
+ badSinceDate = DerGeneralizedTime.GetInstance(seq[3]);
+
+ if (seq.Count > 4)
+ {
+ crlDetails = X509Extensions.GetInstance(seq[4]);
+ }
+ }
+
+ public static RevAnnContent GetInstance(object obj)
+ {
+ if (obj is RevAnnContent)
+ return (RevAnnContent)obj;
+
+ if (obj is Asn1Sequence)
+ return new RevAnnContent((Asn1Sequence)obj);
+
+ throw new ArgumentException("Invalid object: " + obj.GetType().Name, "obj");
+ }
+
+ public virtual PkiStatusEncodable Status
+ {
+ get { return status; }
+ }
+
+ public virtual CertId CertID
+ {
+ get { return certId; }
+ }
+
+ public virtual DerGeneralizedTime WillBeRevokedAt
+ {
+ get { return willBeRevokedAt; }
+ }
+
+ public virtual DerGeneralizedTime BadSinceDate
+ {
+ get { return badSinceDate; }
+ }
+
+ public virtual X509Extensions CrlDetails
+ {
+ get { return crlDetails; }
+ }
+
+ /**
+ * <pre>
+ * RevAnnContent ::= SEQUENCE {
+ * status PKIStatus,
+ * certId CertId,
+ * willBeRevokedAt GeneralizedTime,
+ * badSinceDate GeneralizedTime,
+ * crlDetails Extensions OPTIONAL
+ * -- extra CRL details (e.g., crl number, reason, location, etc.)
+ * }
+ * </pre>
+ * @return a basic ASN.1 object representation.
+ */
+ public override Asn1Object ToAsn1Object()
+ {
+ Asn1EncodableVector v = new Asn1EncodableVector(status, certId, willBeRevokedAt, badSinceDate);
+ v.AddOptional(crlDetails);
+ return new DerSequence(v);
+ }
+ }
+}
diff --git a/Crypto/src/asn1/cmp/RevDetails.cs b/Crypto/src/asn1/cmp/RevDetails.cs
new file mode 100644
index 000000000..1bd95f1db
--- /dev/null
+++ b/Crypto/src/asn1/cmp/RevDetails.cs
@@ -0,0 +1,75 @@
+using System;
+
+using Org.BouncyCastle.Asn1.Crmf;
+using Org.BouncyCastle.Asn1.X509;
+
+namespace Org.BouncyCastle.Asn1.Cmp
+{
+ public class RevDetails
+ : Asn1Encodable
+ {
+ private readonly CertTemplate certDetails;
+ private readonly X509Extensions crlEntryDetails;
+
+ private RevDetails(Asn1Sequence seq)
+ {
+ certDetails = CertTemplate.GetInstance(seq[0]);
+
+ if (seq.Count > 1)
+ {
+ crlEntryDetails = X509Extensions.GetInstance(seq[1]);
+ }
+ }
+
+ public static RevDetails GetInstance(object obj)
+ {
+ if (obj is RevDetails)
+ return (RevDetails)obj;
+
+ if (obj is Asn1Sequence)
+ return new RevDetails((Asn1Sequence)obj);
+
+ throw new ArgumentException("Invalid object: " + obj.GetType().Name, "obj");
+ }
+
+ public RevDetails(CertTemplate certDetails)
+ {
+ this.certDetails = certDetails;
+ }
+
+ public RevDetails(CertTemplate certDetails, X509Extensions crlEntryDetails)
+ {
+ this.crlEntryDetails = crlEntryDetails;
+ }
+
+ public virtual CertTemplate CertDetails
+ {
+ get { return certDetails; }
+ }
+
+ public virtual X509Extensions CrlEntryDetails
+ {
+ get { return crlEntryDetails; }
+ }
+
+ /**
+ * <pre>
+ * RevDetails ::= SEQUENCE {
+ * certDetails CertTemplate,
+ * -- allows requester to specify as much as they can about
+ * -- the cert. for which revocation is requested
+ * -- (e.g., for cases in which serialNumber is not available)
+ * crlEntryDetails Extensions OPTIONAL
+ * -- requested crlEntryExtensions
+ * }
+ * </pre>
+ * @return a basic ASN.1 object representation.
+ */
+ public override Asn1Object ToAsn1Object()
+ {
+ Asn1EncodableVector v = new Asn1EncodableVector(certDetails);
+ v.AddOptional(crlEntryDetails);
+ return new DerSequence(v);
+ }
+ }
+}
diff --git a/Crypto/src/asn1/cmp/RevRepContent.cs b/Crypto/src/asn1/cmp/RevRepContent.cs
new file mode 100644
index 000000000..47987265a
--- /dev/null
+++ b/Crypto/src/asn1/cmp/RevRepContent.cs
@@ -0,0 +1,112 @@
+using System;
+
+using Org.BouncyCastle.Asn1.Crmf;
+using Org.BouncyCastle.Asn1.X509;
+
+namespace Org.BouncyCastle.Asn1.Cmp
+{
+ public class RevRepContent
+ : Asn1Encodable
+ {
+ private readonly Asn1Sequence status;
+ private readonly Asn1Sequence revCerts;
+ private readonly Asn1Sequence crls;
+
+ private RevRepContent(Asn1Sequence seq)
+ {
+ status = Asn1Sequence.GetInstance(seq[0]);
+
+ for (int pos = 1; pos < seq.Count; ++pos)
+ {
+ Asn1TaggedObject tObj = Asn1TaggedObject.GetInstance(seq[pos]);
+
+ if (tObj.TagNo == 0)
+ {
+ revCerts = Asn1Sequence.GetInstance(tObj, true);
+ }
+ else
+ {
+ crls = Asn1Sequence.GetInstance(tObj, true);
+ }
+ }
+ }
+
+ public static RevRepContent GetInstance(object obj)
+ {
+ if (obj is RevRepContent)
+ return (RevRepContent)obj;
+
+ if (obj is Asn1Sequence)
+ return new RevRepContent((Asn1Sequence)obj);
+
+ throw new ArgumentException("Invalid object: " + obj.GetType().Name, "obj");
+ }
+
+ public virtual PkiStatusInfo[] GetStatus()
+ {
+ PkiStatusInfo[] results = new PkiStatusInfo[status.Count];
+ for (int i = 0; i != results.Length; ++i)
+ {
+ results[i] = PkiStatusInfo.GetInstance(status[i]);
+ }
+ return results;
+ }
+
+ public virtual CertId[] GetRevCerts()
+ {
+ if (revCerts == null)
+ return null;
+
+ CertId[] results = new CertId[revCerts.Count];
+ for (int i = 0; i != results.Length; ++i)
+ {
+ results[i] = CertId.GetInstance(revCerts[i]);
+ }
+ return results;
+ }
+
+ public virtual CertificateList[] GetCrls()
+ {
+ if (crls == null)
+ return null;
+
+ CertificateList[] results = new CertificateList[crls.Count];
+ for (int i = 0; i != results.Length; ++i)
+ {
+ results[i] = CertificateList.GetInstance(crls[i]);
+ }
+ return results;
+ }
+
+ /**
+ * <pre>
+ * RevRepContent ::= SEQUENCE {
+ * status SEQUENCE SIZE (1..MAX) OF PKIStatusInfo,
+ * -- in same order as was sent in RevReqContent
+ * revCerts [0] SEQUENCE SIZE (1..MAX) OF CertId OPTIONAL,
+ * -- IDs for which revocation was requested
+ * -- (same order as status)
+ * crls [1] SEQUENCE SIZE (1..MAX) OF CertificateList OPTIONAL
+ * -- the resulting CRLs (there may be more than one)
+ * }
+ * </pre>
+ * @return a basic ASN.1 object representation.
+ */
+ public override Asn1Object ToAsn1Object()
+ {
+ Asn1EncodableVector v = new Asn1EncodableVector(status);
+ AddOptional(v, 0, revCerts);
+ AddOptional(v, 1, crls);
+ return new DerSequence(v);
+ }
+
+ private void AddOptional(Asn1EncodableVector v, int tagNo, Asn1Encodable obj)
+ {
+ if (obj != null)
+ {
+ v.Add(new DerTaggedObject(true, tagNo, obj));
+ }
+ }
+ }
+}
+
diff --git a/Crypto/src/asn1/cmp/RevRepContentBuilder.cs b/Crypto/src/asn1/cmp/RevRepContentBuilder.cs
new file mode 100644
index 000000000..cc17d1d4c
--- /dev/null
+++ b/Crypto/src/asn1/cmp/RevRepContentBuilder.cs
@@ -0,0 +1,55 @@
+using System;
+
+using Org.BouncyCastle.Asn1.Crmf;
+using Org.BouncyCastle.Asn1.X509;
+
+namespace Org.BouncyCastle.Asn1.Cmp
+{
+ public class RevRepContentBuilder
+ {
+ private readonly Asn1EncodableVector status = new Asn1EncodableVector();
+ private readonly Asn1EncodableVector revCerts = new Asn1EncodableVector();
+ private readonly Asn1EncodableVector crls = new Asn1EncodableVector();
+
+ public virtual RevRepContentBuilder Add(PkiStatusInfo status)
+ {
+ this.status.Add(status);
+ return this;
+ }
+
+ public virtual RevRepContentBuilder Add(PkiStatusInfo status, CertId certId)
+ {
+ if (this.status.Count != this.revCerts.Count)
+ throw new InvalidOperationException("status and revCerts sequence must be in common order");
+
+ this.status.Add(status);
+ this.revCerts.Add(certId);
+ return this;
+ }
+
+ public virtual RevRepContentBuilder AddCrl(CertificateList crl)
+ {
+ this.crls.Add(crl);
+ return this;
+ }
+
+ public virtual RevRepContent Build()
+ {
+ Asn1EncodableVector v = new Asn1EncodableVector();
+
+ v.Add(new DerSequence(status));
+
+ if (revCerts.Count != 0)
+ {
+ v.Add(new DerTaggedObject(true, 0, new DerSequence(revCerts)));
+ }
+
+ if (crls.Count != 0)
+ {
+ v.Add(new DerTaggedObject(true, 1, new DerSequence(crls)));
+ }
+
+ return RevRepContent.GetInstance(new DerSequence(v));
+ }
+ }
+}
diff --git a/Crypto/src/asn1/cmp/RevReqContent.cs b/Crypto/src/asn1/cmp/RevReqContent.cs
new file mode 100644
index 000000000..fbf869203
--- /dev/null
+++ b/Crypto/src/asn1/cmp/RevReqContent.cs
@@ -0,0 +1,52 @@
+using System;
+
+namespace Org.BouncyCastle.Asn1.Cmp
+{
+ public class RevReqContent
+ : Asn1Encodable
+ {
+ private readonly Asn1Sequence content;
+
+ private RevReqContent(Asn1Sequence seq)
+ {
+ content = seq;
+ }
+
+ public static RevReqContent GetInstance(object obj)
+ {
+ if (obj is RevReqContent)
+ return (RevReqContent)obj;
+
+ if (obj is Asn1Sequence)
+ return new RevReqContent((Asn1Sequence)obj);
+
+ throw new ArgumentException("Invalid object: " + obj.GetType().Name, "obj");
+ }
+
+ public RevReqContent(params RevDetails[] revDetails)
+ {
+ this.content = new DerSequence(revDetails);
+ }
+
+ public virtual RevDetails[] ToRevDetailsArray()
+ {
+ RevDetails[] result = new RevDetails[content.Count];
+ for (int i = 0; i != result.Length; ++i)
+ {
+ result[i] = RevDetails.GetInstance(content[i]);
+ }
+ return result;
+ }
+
+ /**
+ * <pre>
+ * RevReqContent ::= SEQUENCE OF RevDetails
+ * </pre>
+ * @return a basic ASN.1 object representation.
+ */
+ public override Asn1Object ToAsn1Object()
+ {
+ return content;
+ }
+ }
+}
|