Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/quite/humla-spongycastle.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRoberto Tyley <roberto.tyley@gmail.com>2014-07-15 01:38:01 +0400
committerRoberto Tyley <roberto.tyley@gmail.com>2014-07-26 11:23:17 +0400
commit7cb752aaf746dc0b473afeb9e892b7fbc12666c5 (patch)
treecc4f91ddc18332b5adbe82e3fcb040d976c90105 /core/src/main/java/org/spongycastle/asn1/cmp
parent551830f8ea5177042af2c7dd1fc90888bc67387d (diff)
Execute become-spongy.sh
https://github.com/rtyley/spongycastle/blob/3040af/become-spongy.sh
Diffstat (limited to 'core/src/main/java/org/spongycastle/asn1/cmp')
-rw-r--r--core/src/main/java/org/spongycastle/asn1/cmp/CAKeyUpdAnnContent.java80
-rw-r--r--core/src/main/java/org/spongycastle/asn1/cmp/CMPCertificate.java92
-rw-r--r--core/src/main/java/org/spongycastle/asn1/cmp/CMPObjectIdentifiers.java141
-rw-r--r--core/src/main/java/org/spongycastle/asn1/cmp/CRLAnnContent.java61
-rw-r--r--core/src/main/java/org/spongycastle/asn1/cmp/CertConfirmContent.java54
-rw-r--r--core/src/main/java/org/spongycastle/asn1/cmp/CertOrEncCert.java96
-rw-r--r--core/src/main/java/org/spongycastle/asn1/cmp/CertRepMessage.java123
-rw-r--r--core/src/main/java/org/spongycastle/asn1/cmp/CertResponse.java139
-rw-r--r--core/src/main/java/org/spongycastle/asn1/cmp/CertStatus.java102
-rw-r--r--core/src/main/java/org/spongycastle/asn1/cmp/CertifiedKeyPair.java127
-rw-r--r--core/src/main/java/org/spongycastle/asn1/cmp/Challenge.java120
-rw-r--r--core/src/main/java/org/spongycastle/asn1/cmp/ErrorMsgContent.java121
-rw-r--r--core/src/main/java/org/spongycastle/asn1/cmp/GenMsgContent.java71
-rw-r--r--core/src/main/java/org/spongycastle/asn1/cmp/GenRepContent.java71
-rw-r--r--core/src/main/java/org/spongycastle/asn1/cmp/InfoTypeAndValue.java132
-rw-r--r--core/src/main/java/org/spongycastle/asn1/cmp/KeyRecRepContent.java142
-rw-r--r--core/src/main/java/org/spongycastle/asn1/cmp/OOBCertHash.java117
-rw-r--r--core/src/main/java/org/spongycastle/asn1/cmp/PBMParameter.java117
-rw-r--r--core/src/main/java/org/spongycastle/asn1/cmp/PKIBody.java194
-rw-r--r--core/src/main/java/org/spongycastle/asn1/cmp/PKIConfirmContent.java48
-rw-r--r--core/src/main/java/org/spongycastle/asn1/cmp/PKIFailureInfo.java126
-rw-r--r--core/src/main/java/org/spongycastle/asn1/cmp/PKIFreeText.java115
-rw-r--r--core/src/main/java/org/spongycastle/asn1/cmp/PKIHeader.java260
-rw-r--r--core/src/main/java/org/spongycastle/asn1/cmp/PKIHeaderBuilder.java243
-rw-r--r--core/src/main/java/org/spongycastle/asn1/cmp/PKIMessage.java166
-rw-r--r--core/src/main/java/org/spongycastle/asn1/cmp/PKIMessages.java71
-rw-r--r--core/src/main/java/org/spongycastle/asn1/cmp/PKIStatus.java64
-rw-r--r--core/src/main/java/org/spongycastle/asn1/cmp/PKIStatusInfo.java165
-rw-r--r--core/src/main/java/org/spongycastle/asn1/cmp/POPODecKeyChallContent.java54
-rw-r--r--core/src/main/java/org/spongycastle/asn1/cmp/POPODecKeyRespContent.java55
-rw-r--r--core/src/main/java/org/spongycastle/asn1/cmp/PollRepContent.java119
-rw-r--r--core/src/main/java/org/spongycastle/asn1/cmp/PollReqContent.java80
-rw-r--r--core/src/main/java/org/spongycastle/asn1/cmp/ProtectedPart.java70
-rw-r--r--core/src/main/java/org/spongycastle/asn1/cmp/RevAnnContent.java103
-rw-r--r--core/src/main/java/org/spongycastle/asn1/cmp/RevDetails.java100
-rw-r--r--core/src/main/java/org/spongycastle/asn1/cmp/RevRepContent.java137
-rw-r--r--core/src/main/java/org/spongycastle/asn1/cmp/RevRepContentBuilder.java59
-rw-r--r--core/src/main/java/org/spongycastle/asn1/cmp/RevReqContent.java73
38 files changed, 4208 insertions, 0 deletions
diff --git a/core/src/main/java/org/spongycastle/asn1/cmp/CAKeyUpdAnnContent.java b/core/src/main/java/org/spongycastle/asn1/cmp/CAKeyUpdAnnContent.java
new file mode 100644
index 00000000..ddc4c252
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/cmp/CAKeyUpdAnnContent.java
@@ -0,0 +1,80 @@
+package org.spongycastle.asn1.cmp;
+
+import org.spongycastle.asn1.ASN1EncodableVector;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.DERSequence;
+
+public class CAKeyUpdAnnContent
+ extends ASN1Object
+{
+ private CMPCertificate oldWithNew;
+ private CMPCertificate newWithOld;
+ private CMPCertificate newWithNew;
+
+ private CAKeyUpdAnnContent(ASN1Sequence seq)
+ {
+ oldWithNew = CMPCertificate.getInstance(seq.getObjectAt(0));
+ newWithOld = CMPCertificate.getInstance(seq.getObjectAt(1));
+ newWithNew = CMPCertificate.getInstance(seq.getObjectAt(2));
+ }
+
+ public static CAKeyUpdAnnContent getInstance(Object o)
+ {
+ if (o instanceof CAKeyUpdAnnContent)
+ {
+ return (CAKeyUpdAnnContent)o;
+ }
+
+ if (o != null)
+ {
+ return new CAKeyUpdAnnContent(ASN1Sequence.getInstance(o));
+ }
+
+ return null;
+ }
+
+ public CAKeyUpdAnnContent(CMPCertificate oldWithNew, CMPCertificate newWithOld, CMPCertificate newWithNew)
+ {
+ this.oldWithNew = oldWithNew;
+ this.newWithOld = newWithOld;
+ this.newWithNew = newWithNew;
+ }
+
+ public CMPCertificate getOldWithNew()
+ {
+ return oldWithNew;
+ }
+
+ public CMPCertificate getNewWithOld()
+ {
+ return newWithOld;
+ }
+
+ public CMPCertificate getNewWithNew()
+ {
+ 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 ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(oldWithNew);
+ v.add(newWithOld);
+ v.add(newWithNew);
+
+ return new DERSequence(v);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/cmp/CMPCertificate.java b/core/src/main/java/org/spongycastle/asn1/cmp/CMPCertificate.java
new file mode 100644
index 00000000..22dcb3b8
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/cmp/CMPCertificate.java
@@ -0,0 +1,92 @@
+package org.spongycastle.asn1.cmp;
+
+import org.spongycastle.asn1.ASN1Choice;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.ASN1TaggedObject;
+import org.spongycastle.asn1.DERTaggedObject;
+import org.spongycastle.asn1.x509.AttributeCertificate;
+import org.spongycastle.asn1.x509.Certificate;
+
+public class CMPCertificate
+ extends ASN1Object
+ implements ASN1Choice
+{
+ private Certificate x509v3PKCert;
+ private AttributeCertificate x509v2AttrCert;
+
+ /**
+ * Note: the addition of attribute certificates is a BC extension.
+ */
+ public CMPCertificate(AttributeCertificate x509v2AttrCert)
+ {
+ this.x509v2AttrCert = x509v2AttrCert;
+ }
+
+ public CMPCertificate(Certificate x509v3PKCert)
+ {
+ if (x509v3PKCert.getVersionNumber() != 3)
+ {
+ throw new IllegalArgumentException("only version 3 certificates allowed");
+ }
+
+ this.x509v3PKCert = x509v3PKCert;
+ }
+
+ public static CMPCertificate getInstance(Object o)
+ {
+ if (o == null || o instanceof CMPCertificate)
+ {
+ return (CMPCertificate)o;
+ }
+
+ if (o instanceof ASN1Sequence || o instanceof byte[])
+ {
+ return new CMPCertificate(Certificate.getInstance(o));
+ }
+
+ if (o instanceof ASN1TaggedObject)
+ {
+ return new CMPCertificate(AttributeCertificate.getInstance(((ASN1TaggedObject)o).getObject()));
+ }
+
+ throw new IllegalArgumentException("Invalid object: " + o.getClass().getName());
+ }
+
+ public boolean isX509v3PKCert()
+ {
+ return x509v3PKCert != null;
+ }
+
+ public Certificate getX509v3PKCert()
+ {
+ return x509v3PKCert;
+ }
+
+ public AttributeCertificate getX509v2AttrCert()
+ {
+ 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 ASN1Primitive toASN1Primitive()
+ {
+ if (x509v2AttrCert != null)
+ { // explicit following CMP conventions
+ return new DERTaggedObject(true, 1, x509v2AttrCert);
+ }
+
+ return x509v3PKCert.toASN1Primitive();
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/cmp/CMPObjectIdentifiers.java b/core/src/main/java/org/spongycastle/asn1/cmp/CMPObjectIdentifiers.java
new file mode 100644
index 00000000..c7cbc5a5
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/cmp/CMPObjectIdentifiers.java
@@ -0,0 +1,141 @@
+package org.spongycastle.asn1.cmp;
+
+import org.spongycastle.asn1.ASN1ObjectIdentifier;
+
+public interface CMPObjectIdentifiers
+{
+ // RFC 4210
+
+ /** id-PasswordBasedMac OBJECT IDENTIFIER ::= {1 2 840 113533 7 66 13} */
+ static final ASN1ObjectIdentifier passwordBasedMac = new ASN1ObjectIdentifier("1.2.840.113533.7.66.13");
+
+ /** id-DHBasedMac OBJECT IDENTIFIER ::= {1 2 840 113533 7 66 30} */
+ static final ASN1ObjectIdentifier dhBasedMac = new ASN1ObjectIdentifier("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}
+
+ /** RFC 4120: it-id: PKIX.4 = 1.3.6.1.5.5.7.4 */
+
+ /** RFC 4120: 1.3.6.1.5.5.7.4.1 */
+ static final ASN1ObjectIdentifier it_caProtEncCert = new ASN1ObjectIdentifier("1.3.6.1.5.5.7.4.1");
+ /** RFC 4120: 1.3.6.1.5.5.7.4.2 */
+ static final ASN1ObjectIdentifier it_signKeyPairTypes = new ASN1ObjectIdentifier("1.3.6.1.5.5.7.4.2");
+ /** RFC 4120: 1.3.6.1.5.5.7.4.3 */
+ static final ASN1ObjectIdentifier it_encKeyPairTypes = new ASN1ObjectIdentifier("1.3.6.1.5.5.7.4.3");
+ /** RFC 4120: 1.3.6.1.5.5.7.4.4 */
+ static final ASN1ObjectIdentifier it_preferredSymAlg = new ASN1ObjectIdentifier("1.3.6.1.5.5.7.4.4");
+ /** RFC 4120: 1.3.6.1.5.5.7.4.5 */
+ static final ASN1ObjectIdentifier it_caKeyUpdateInfo = new ASN1ObjectIdentifier("1.3.6.1.5.5.7.4.5");
+ /** RFC 4120: 1.3.6.1.5.5.7.4.6 */
+ static final ASN1ObjectIdentifier it_currentCRL = new ASN1ObjectIdentifier("1.3.6.1.5.5.7.4.6");
+ /** RFC 4120: 1.3.6.1.5.5.7.4.7 */
+ static final ASN1ObjectIdentifier it_unsupportedOIDs = new ASN1ObjectIdentifier("1.3.6.1.5.5.7.4.7");
+ /** RFC 4120: 1.3.6.1.5.5.7.4.10 */
+ static final ASN1ObjectIdentifier it_keyPairParamReq = new ASN1ObjectIdentifier("1.3.6.1.5.5.7.4.10");
+ /** RFC 4120: 1.3.6.1.5.5.7.4.11 */
+ static final ASN1ObjectIdentifier it_keyPairParamRep = new ASN1ObjectIdentifier("1.3.6.1.5.5.7.4.11");
+ /** RFC 4120: 1.3.6.1.5.5.7.4.12 */
+ static final ASN1ObjectIdentifier it_revPassphrase = new ASN1ObjectIdentifier("1.3.6.1.5.5.7.4.12");
+ /** RFC 4120: 1.3.6.1.5.5.7.4.13 */
+ static final ASN1ObjectIdentifier it_implicitConfirm = new ASN1ObjectIdentifier("1.3.6.1.5.5.7.4.13");
+ /** RFC 4120: 1.3.6.1.5.5.7.4.14 */
+ static final ASN1ObjectIdentifier it_confirmWaitTime = new ASN1ObjectIdentifier("1.3.6.1.5.5.7.4.14");
+ /** RFC 4120: 1.3.6.1.5.5.7.4.15 */
+ static final ASN1ObjectIdentifier it_origPKIMessage = new ASN1ObjectIdentifier("1.3.6.1.5.5.7.4.15");
+ /** RFC 4120: 1.3.6.1.5.5.7.4.16 */
+ static final ASN1ObjectIdentifier it_suppLangTags = new ASN1ObjectIdentifier("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) }
+
+ /** RFC 4211: it-pkip: PKIX.5 = 1.3.6.1.5.5.7.5 */
+ static final ASN1ObjectIdentifier id_pkip = new ASN1ObjectIdentifier("1.3.6.1.5.5.7.5");
+
+ /** RFC 4211: it-regCtrl: 1.3.6.1.5.5.7.5.1 */
+ static final ASN1ObjectIdentifier id_regCtrl = new ASN1ObjectIdentifier("1.3.6.1.5.5.7.5.1");
+ /** RFC 4211: it-regInfo: 1.3.6.1.5.5.7.5.2 */
+ static final ASN1ObjectIdentifier id_regInfo = new ASN1ObjectIdentifier("1.3.6.1.5.5.7.5.2");
+
+
+ /** 1.3.6.1.5.5.7.5.1.1 */
+ static final ASN1ObjectIdentifier regCtrl_regToken = new ASN1ObjectIdentifier("1.3.6.1.5.5.7.5.1.1");
+ /** 1.3.6.1.5.5.7.5.1.2 */
+ static final ASN1ObjectIdentifier regCtrl_authenticator = new ASN1ObjectIdentifier("1.3.6.1.5.5.7.5.1.2");
+ /** 1.3.6.1.5.5.7.5.1.3 */
+ static final ASN1ObjectIdentifier regCtrl_pkiPublicationInfo = new ASN1ObjectIdentifier("1.3.6.1.5.5.7.5.1.3");
+ /** 1.3.6.1.5.5.7.5.1.4 */
+ static final ASN1ObjectIdentifier regCtrl_pkiArchiveOptions = new ASN1ObjectIdentifier("1.3.6.1.5.5.7.5.1.4");
+ /** 1.3.6.1.5.5.7.5.1.5 */
+ static final ASN1ObjectIdentifier regCtrl_oldCertID = new ASN1ObjectIdentifier("1.3.6.1.5.5.7.5.1.5");
+ /** 1.3.6.1.5.5.7.5.1.6 */
+ static final ASN1ObjectIdentifier regCtrl_protocolEncrKey = new ASN1ObjectIdentifier("1.3.6.1.5.5.7.5.1.6");
+
+ /** From RFC4210:
+ * id-regCtrl-altCertTemplate OBJECT IDENTIFIER ::= {id-regCtrl 7}; 1.3.6.1.5.5.7.1.7 */
+ static final ASN1ObjectIdentifier regCtrl_altCertTemplate = new ASN1ObjectIdentifier("1.3.6.1.5.5.7.5.1.7");
+
+ /** RFC 4211: it-regInfo-utf8Pairs: 1.3.6.1.5.5.7.5.2.1 */
+ static final ASN1ObjectIdentifier regInfo_utf8Pairs = new ASN1ObjectIdentifier("1.3.6.1.5.5.7.5.2.1");
+ /** RFC 4211: it-regInfo-certReq: 1.3.6.1.5.5.7.5.2.1 */
+ static final ASN1ObjectIdentifier regInfo_certReq = new ASN1ObjectIdentifier("1.3.6.1.5.5.7.5.2.2");
+
+ /**
+ * 1.2.840.113549.1.9.16.1.21
+ * <p>
+ * id-ct OBJECT IDENTIFIER ::= { id-smime 1 } -- content types
+ * <p>
+ * id-ct-encKeyWithID OBJECT IDENTIFIER ::= {id-ct 21}
+ */
+ static final ASN1ObjectIdentifier ct_encKeyWithID = new ASN1ObjectIdentifier("1.2.840.113549.1.9.16.1.21");
+
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/cmp/CRLAnnContent.java b/core/src/main/java/org/spongycastle/asn1/cmp/CRLAnnContent.java
new file mode 100644
index 00000000..513baeb9
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/cmp/CRLAnnContent.java
@@ -0,0 +1,61 @@
+package org.spongycastle.asn1.cmp;
+
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.DERSequence;
+import org.spongycastle.asn1.x509.CertificateList;
+
+public class CRLAnnContent
+ extends ASN1Object
+{
+ private ASN1Sequence content;
+
+ private CRLAnnContent(ASN1Sequence seq)
+ {
+ content = seq;
+ }
+
+ public static CRLAnnContent getInstance(Object o)
+ {
+ if (o instanceof CRLAnnContent)
+ {
+ return (CRLAnnContent)o;
+ }
+
+ if (o != null)
+ {
+ return new CRLAnnContent(ASN1Sequence.getInstance(o));
+ }
+
+ return null;
+ }
+
+ public CRLAnnContent(CertificateList crl)
+ {
+ this.content = new DERSequence(crl);
+ }
+
+ public CertificateList[] getCertificateLists()
+ {
+ CertificateList[] result = new CertificateList[content.size()];
+
+ for (int i = 0; i != result.length; i++)
+ {
+ result[i] = CertificateList.getInstance(content.getObjectAt(i));
+ }
+
+ return result;
+ }
+
+ /**
+ * <pre>
+ * CRLAnnContent ::= SEQUENCE OF CertificateList
+ * </pre>
+ * @return a basic ASN.1 object representation.
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ return content;
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/cmp/CertConfirmContent.java b/core/src/main/java/org/spongycastle/asn1/cmp/CertConfirmContent.java
new file mode 100644
index 00000000..974eb757
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/cmp/CertConfirmContent.java
@@ -0,0 +1,54 @@
+package org.spongycastle.asn1.cmp;
+
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1Sequence;
+
+public class CertConfirmContent
+ extends ASN1Object
+{
+ private ASN1Sequence content;
+
+ private CertConfirmContent(ASN1Sequence seq)
+ {
+ content = seq;
+ }
+
+ public static CertConfirmContent getInstance(Object o)
+ {
+ if (o instanceof CertConfirmContent)
+ {
+ return (CertConfirmContent)o;
+ }
+
+ if (o != null)
+ {
+ return new CertConfirmContent(ASN1Sequence.getInstance(o));
+ }
+
+ return null;
+ }
+
+ public CertStatus[] toCertStatusArray()
+ {
+ CertStatus[] result = new CertStatus[content.size()];
+
+ for (int i = 0; i != result.length; i++)
+ {
+ result[i] = CertStatus.getInstance(content.getObjectAt(i));
+ }
+
+ return result;
+ }
+
+ /**
+ * <pre>
+ * CertConfirmContent ::= SEQUENCE OF CertStatus
+ * </pre>
+ * @return a basic ASN.1 object representation.
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ return content;
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/cmp/CertOrEncCert.java b/core/src/main/java/org/spongycastle/asn1/cmp/CertOrEncCert.java
new file mode 100644
index 00000000..ed16a650
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/cmp/CertOrEncCert.java
@@ -0,0 +1,96 @@
+package org.spongycastle.asn1.cmp;
+
+import org.spongycastle.asn1.ASN1Choice;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1TaggedObject;
+import org.spongycastle.asn1.DERTaggedObject;
+import org.spongycastle.asn1.crmf.EncryptedValue;
+
+public class CertOrEncCert
+ extends ASN1Object
+ implements ASN1Choice
+{
+ private CMPCertificate certificate;
+ private EncryptedValue encryptedCert;
+
+ private CertOrEncCert(ASN1TaggedObject tagged)
+ {
+ if (tagged.getTagNo() == 0)
+ {
+ certificate = CMPCertificate.getInstance(tagged.getObject());
+ }
+ else if (tagged.getTagNo() == 1)
+ {
+ encryptedCert = EncryptedValue.getInstance(tagged.getObject());
+ }
+ else
+ {
+ throw new IllegalArgumentException("unknown tag: " + tagged.getTagNo());
+ }
+ }
+
+ public static CertOrEncCert getInstance(Object o)
+ {
+ if (o instanceof CertOrEncCert)
+ {
+ return (CertOrEncCert)o;
+ }
+
+ if (o instanceof ASN1TaggedObject)
+ {
+ return new CertOrEncCert((ASN1TaggedObject)o);
+ }
+
+ return null;
+ }
+
+ public CertOrEncCert(CMPCertificate certificate)
+ {
+ if (certificate == null)
+ {
+ throw new IllegalArgumentException("'certificate' cannot be null");
+ }
+
+ this.certificate = certificate;
+ }
+
+ public CertOrEncCert(EncryptedValue encryptedCert)
+ {
+ if (encryptedCert == null)
+ {
+ throw new IllegalArgumentException("'encryptedCert' cannot be null");
+ }
+
+ this.encryptedCert = encryptedCert;
+ }
+
+ public CMPCertificate getCertificate()
+ {
+ return certificate;
+ }
+
+ public EncryptedValue getEncryptedCert()
+ {
+ return encryptedCert;
+ }
+
+ /**
+ * <pre>
+ * CertOrEncCert ::= CHOICE {
+ * certificate [0] CMPCertificate,
+ * encryptedCert [1] EncryptedValue
+ * }
+ * </pre>
+ * @return a basic ASN.1 object representation.
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ if (certificate != null)
+ {
+ return new DERTaggedObject(true, 0, certificate);
+ }
+
+ return new DERTaggedObject(true, 1, encryptedCert);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/cmp/CertRepMessage.java b/core/src/main/java/org/spongycastle/asn1/cmp/CertRepMessage.java
new file mode 100644
index 00000000..3f63a4ac
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/cmp/CertRepMessage.java
@@ -0,0 +1,123 @@
+package org.spongycastle.asn1.cmp;
+
+import org.spongycastle.asn1.ASN1EncodableVector;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.ASN1TaggedObject;
+import org.spongycastle.asn1.DERSequence;
+import org.spongycastle.asn1.DERTaggedObject;
+
+public class CertRepMessage
+ extends ASN1Object
+{
+ private ASN1Sequence caPubs;
+ private ASN1Sequence response;
+
+ private CertRepMessage(ASN1Sequence seq)
+ {
+ int index = 0;
+
+ if (seq.size() > 1)
+ {
+ caPubs = ASN1Sequence.getInstance((ASN1TaggedObject)seq.getObjectAt(index++), true);
+ }
+
+ response = ASN1Sequence.getInstance(seq.getObjectAt(index));
+ }
+
+ public static CertRepMessage getInstance(Object o)
+ {
+ if (o instanceof CertRepMessage)
+ {
+ return (CertRepMessage)o;
+ }
+
+ if (o != null)
+ {
+ return new CertRepMessage(ASN1Sequence.getInstance(o));
+ }
+
+ return null;
+ }
+
+ public CertRepMessage(CMPCertificate[] caPubs, CertResponse[] response)
+ {
+ if (response == null)
+ {
+ throw new IllegalArgumentException("'response' cannot be null");
+ }
+
+ if (caPubs != null)
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+ for (int i = 0; i < caPubs.length; i++)
+ {
+ v.add(caPubs[i]);
+ }
+ this.caPubs = new DERSequence(v);
+ }
+
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+ for (int i = 0; i < response.length; i++)
+ {
+ v.add(response[i]);
+ }
+ this.response = new DERSequence(v);
+ }
+ }
+
+ public CMPCertificate[] getCaPubs()
+ {
+ if (caPubs == null)
+ {
+ return null;
+ }
+
+ CMPCertificate[] results = new CMPCertificate[caPubs.size()];
+
+ for (int i = 0; i != results.length; i++)
+ {
+ results[i] = CMPCertificate.getInstance(caPubs.getObjectAt(i));
+ }
+
+ return results;
+ }
+
+ public CertResponse[] getResponse()
+ {
+ CertResponse[] results = new CertResponse[response.size()];
+
+ for (int i = 0; i != results.length; i++)
+ {
+ results[i] = CertResponse.getInstance(response.getObjectAt(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 ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ if (caPubs != null)
+ {
+ v.add(new DERTaggedObject(true, 1, caPubs));
+ }
+
+ v.add(response);
+
+ return new DERSequence(v);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/cmp/CertResponse.java b/core/src/main/java/org/spongycastle/asn1/cmp/CertResponse.java
new file mode 100644
index 00000000..9efcff68
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/cmp/CertResponse.java
@@ -0,0 +1,139 @@
+package org.spongycastle.asn1.cmp;
+
+import org.spongycastle.asn1.ASN1Encodable;
+import org.spongycastle.asn1.ASN1EncodableVector;
+import org.spongycastle.asn1.ASN1Integer;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1OctetString;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.DERSequence;
+
+public class CertResponse
+ extends ASN1Object
+{
+ private ASN1Integer certReqId;
+ private PKIStatusInfo status;
+ private CertifiedKeyPair certifiedKeyPair;
+ private ASN1OctetString rspInfo;
+
+ private CertResponse(ASN1Sequence seq)
+ {
+ certReqId = ASN1Integer.getInstance(seq.getObjectAt(0));
+ status = PKIStatusInfo.getInstance(seq.getObjectAt(1));
+
+ if (seq.size() >= 3)
+ {
+ if (seq.size() == 3)
+ {
+ ASN1Encodable o = seq.getObjectAt(2);
+ if (o instanceof ASN1OctetString)
+ {
+ rspInfo = ASN1OctetString.getInstance(o);
+ }
+ else
+ {
+ certifiedKeyPair = CertifiedKeyPair.getInstance(o);
+ }
+ }
+ else
+ {
+ certifiedKeyPair = CertifiedKeyPair.getInstance(seq.getObjectAt(2));
+ rspInfo = ASN1OctetString.getInstance(seq.getObjectAt(3));
+ }
+ }
+ }
+
+ public static CertResponse getInstance(Object o)
+ {
+ if (o instanceof CertResponse)
+ {
+ return (CertResponse)o;
+ }
+
+ if (o != null)
+ {
+ return new CertResponse(ASN1Sequence.getInstance(o));
+ }
+
+ return null;
+ }
+
+ public CertResponse(
+ ASN1Integer certReqId,
+ PKIStatusInfo status)
+ {
+ this(certReqId, status, null, null);
+ }
+
+ public CertResponse(
+ ASN1Integer certReqId,
+ PKIStatusInfo status,
+ CertifiedKeyPair certifiedKeyPair,
+ ASN1OctetString rspInfo)
+ {
+ if (certReqId == null)
+ {
+ throw new IllegalArgumentException("'certReqId' cannot be null");
+ }
+ if (status == null)
+ {
+ throw new IllegalArgumentException("'status' cannot be null");
+ }
+ this.certReqId = certReqId;
+ this.status = status;
+ this.certifiedKeyPair = certifiedKeyPair;
+ this.rspInfo = rspInfo;
+ }
+
+ public ASN1Integer getCertReqId()
+ {
+ return certReqId;
+ }
+
+ public PKIStatusInfo getStatus()
+ {
+ return status;
+ }
+
+ public CertifiedKeyPair getCertifiedKeyPair()
+ {
+ 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 ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(certReqId);
+ v.add(status);
+
+ if (certifiedKeyPair != null)
+ {
+ v.add(certifiedKeyPair);
+ }
+
+ if (rspInfo != null)
+ {
+ v.add(rspInfo);
+ }
+
+ return new DERSequence(v);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/cmp/CertStatus.java b/core/src/main/java/org/spongycastle/asn1/cmp/CertStatus.java
new file mode 100644
index 00000000..86664eed
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/cmp/CertStatus.java
@@ -0,0 +1,102 @@
+package org.spongycastle.asn1.cmp;
+
+import java.math.BigInteger;
+
+import org.spongycastle.asn1.ASN1EncodableVector;
+import org.spongycastle.asn1.ASN1Integer;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1OctetString;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.DEROctetString;
+import org.spongycastle.asn1.DERSequence;
+
+public class CertStatus
+ extends ASN1Object
+{
+ private ASN1OctetString certHash;
+ private ASN1Integer certReqId;
+ private PKIStatusInfo statusInfo;
+
+ private CertStatus(ASN1Sequence seq)
+ {
+ certHash = ASN1OctetString.getInstance(seq.getObjectAt(0));
+ certReqId = ASN1Integer.getInstance(seq.getObjectAt(1));
+
+ if (seq.size() > 2)
+ {
+ statusInfo = PKIStatusInfo.getInstance(seq.getObjectAt(2));
+ }
+ }
+
+ public CertStatus(byte[] certHash, BigInteger certReqId)
+ {
+ this.certHash = new DEROctetString(certHash);
+ this.certReqId = new ASN1Integer(certReqId);
+ }
+
+ public CertStatus(byte[] certHash, BigInteger certReqId, PKIStatusInfo statusInfo)
+ {
+ this.certHash = new DEROctetString(certHash);
+ this.certReqId = new ASN1Integer(certReqId);
+ this.statusInfo = statusInfo;
+ }
+
+ public static CertStatus getInstance(Object o)
+ {
+ if (o instanceof CertStatus)
+ {
+ return (CertStatus)o;
+ }
+
+ if (o != null)
+ {
+ return new CertStatus(ASN1Sequence.getInstance(o));
+ }
+
+ return null;
+ }
+
+ public ASN1OctetString getCertHash()
+ {
+ return certHash;
+ }
+
+ public ASN1Integer getCertReqId()
+ {
+ return certReqId;
+ }
+
+ public PKIStatusInfo getStatusInfo()
+ {
+ 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 ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(certHash);
+ v.add(certReqId);
+
+ if (statusInfo != null)
+ {
+ v.add(statusInfo);
+ }
+
+ return new DERSequence(v);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/cmp/CertifiedKeyPair.java b/core/src/main/java/org/spongycastle/asn1/cmp/CertifiedKeyPair.java
new file mode 100644
index 00000000..500c9d03
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/cmp/CertifiedKeyPair.java
@@ -0,0 +1,127 @@
+package org.spongycastle.asn1.cmp;
+
+import org.spongycastle.asn1.ASN1EncodableVector;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.ASN1TaggedObject;
+import org.spongycastle.asn1.DERSequence;
+import org.spongycastle.asn1.DERTaggedObject;
+import org.spongycastle.asn1.crmf.EncryptedValue;
+import org.spongycastle.asn1.crmf.PKIPublicationInfo;
+
+public class CertifiedKeyPair
+ extends ASN1Object
+{
+ private CertOrEncCert certOrEncCert;
+ private EncryptedValue privateKey;
+ private PKIPublicationInfo publicationInfo;
+
+ private CertifiedKeyPair(ASN1Sequence seq)
+ {
+ certOrEncCert = CertOrEncCert.getInstance(seq.getObjectAt(0));
+
+ if (seq.size() >= 2)
+ {
+ if (seq.size() == 2)
+ {
+ ASN1TaggedObject tagged = ASN1TaggedObject.getInstance(seq.getObjectAt(1));
+ if (tagged.getTagNo() == 0)
+ {
+ privateKey = EncryptedValue.getInstance(tagged.getObject());
+ }
+ else
+ {
+ publicationInfo = PKIPublicationInfo.getInstance(tagged.getObject());
+ }
+ }
+ else
+ {
+ privateKey = EncryptedValue.getInstance(ASN1TaggedObject.getInstance(seq.getObjectAt(1)));
+ publicationInfo = PKIPublicationInfo.getInstance(ASN1TaggedObject.getInstance(seq.getObjectAt(2)));
+ }
+ }
+ }
+
+ public static CertifiedKeyPair getInstance(Object o)
+ {
+ if (o instanceof CertifiedKeyPair)
+ {
+ return (CertifiedKeyPair)o;
+ }
+
+ if (o != null)
+ {
+ return new CertifiedKeyPair(ASN1Sequence.getInstance(o));
+ }
+
+ return null;
+ }
+
+ public CertifiedKeyPair(
+ CertOrEncCert certOrEncCert)
+ {
+ this(certOrEncCert, null, null);
+ }
+
+ public CertifiedKeyPair(
+ CertOrEncCert certOrEncCert,
+ EncryptedValue privateKey,
+ PKIPublicationInfo publicationInfo
+ )
+ {
+ if (certOrEncCert == null)
+ {
+ throw new IllegalArgumentException("'certOrEncCert' cannot be null");
+ }
+
+ this.certOrEncCert = certOrEncCert;
+ this.privateKey = privateKey;
+ this.publicationInfo = publicationInfo;
+ }
+
+ public CertOrEncCert getCertOrEncCert()
+ {
+ return certOrEncCert;
+ }
+
+ public EncryptedValue getPrivateKey()
+ {
+ return privateKey;
+ }
+
+ public PKIPublicationInfo getPublicationInfo()
+ {
+ 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 ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(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/core/src/main/java/org/spongycastle/asn1/cmp/Challenge.java b/core/src/main/java/org/spongycastle/asn1/cmp/Challenge.java
new file mode 100644
index 00000000..ef02b28b
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/cmp/Challenge.java
@@ -0,0 +1,120 @@
+package org.spongycastle.asn1.cmp;
+
+import org.spongycastle.asn1.ASN1Encodable;
+import org.spongycastle.asn1.ASN1EncodableVector;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1OctetString;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.DEROctetString;
+import org.spongycastle.asn1.DERSequence;
+import org.spongycastle.asn1.x509.AlgorithmIdentifier;
+
+public class Challenge
+ extends ASN1Object
+{
+ private AlgorithmIdentifier owf;
+ private ASN1OctetString witness;
+ private ASN1OctetString challenge;
+
+ private Challenge(ASN1Sequence seq)
+ {
+ int index = 0;
+
+ if (seq.size() == 3)
+ {
+ owf = AlgorithmIdentifier.getInstance(seq.getObjectAt(index++));
+ }
+
+ witness = ASN1OctetString.getInstance(seq.getObjectAt(index++));
+ challenge = ASN1OctetString.getInstance(seq.getObjectAt(index));
+ }
+
+ public static Challenge getInstance(Object o)
+ {
+ if (o instanceof Challenge)
+ {
+ return (Challenge)o;
+ }
+
+ if (o != null)
+ {
+ return new Challenge(ASN1Sequence.getInstance(o));
+ }
+
+ return null;
+ }
+
+ public Challenge(byte[] witness, byte[] challenge)
+ {
+ this(null, witness, challenge);
+ }
+
+ public Challenge(AlgorithmIdentifier owf, byte[] witness, byte[] challenge)
+ {
+ this.owf = owf;
+ this.witness = new DEROctetString(witness);
+ this.challenge = new DEROctetString(challenge);
+ }
+
+ public AlgorithmIdentifier getOwf()
+ {
+ return owf;
+ }
+
+ public byte[] getWitness()
+ {
+ return witness.getOctets();
+ }
+
+ public byte[] getChallenge()
+ {
+ return challenge.getOctets();
+ }
+
+ /**
+ * <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 ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ addOptional(v, owf);
+ v.add(witness);
+ v.add(challenge);
+
+ return new DERSequence(v);
+ }
+
+ private void addOptional(ASN1EncodableVector v, ASN1Encodable obj)
+ {
+ if (obj != null)
+ {
+ v.add(obj);
+ }
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/cmp/ErrorMsgContent.java b/core/src/main/java/org/spongycastle/asn1/cmp/ErrorMsgContent.java
new file mode 100644
index 00000000..e7ef5716
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/cmp/ErrorMsgContent.java
@@ -0,0 +1,121 @@
+package org.spongycastle.asn1.cmp;
+
+import java.util.Enumeration;
+
+import org.spongycastle.asn1.ASN1Encodable;
+import org.spongycastle.asn1.ASN1EncodableVector;
+import org.spongycastle.asn1.ASN1Integer;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.DERSequence;
+
+public class ErrorMsgContent
+ extends ASN1Object
+{
+ private PKIStatusInfo pkiStatusInfo;
+ private ASN1Integer errorCode;
+ private PKIFreeText errorDetails;
+
+ private ErrorMsgContent(ASN1Sequence seq)
+ {
+ Enumeration en = seq.getObjects();
+
+ pkiStatusInfo = PKIStatusInfo.getInstance(en.nextElement());
+
+ while (en.hasMoreElements())
+ {
+ Object o = en.nextElement();
+
+ if (o instanceof ASN1Integer)
+ {
+ errorCode = ASN1Integer.getInstance(o);
+ }
+ else
+ {
+ errorDetails = PKIFreeText.getInstance(o);
+ }
+ }
+ }
+
+ public static ErrorMsgContent getInstance(Object o)
+ {
+ if (o instanceof ErrorMsgContent)
+ {
+ return (ErrorMsgContent)o;
+ }
+
+ if (o != null)
+ {
+ return new ErrorMsgContent(ASN1Sequence.getInstance(o));
+ }
+
+ return null;
+ }
+
+ public ErrorMsgContent(PKIStatusInfo pkiStatusInfo)
+ {
+ this(pkiStatusInfo, null, null);
+ }
+
+ public ErrorMsgContent(
+ PKIStatusInfo pkiStatusInfo,
+ ASN1Integer errorCode,
+ PKIFreeText errorDetails)
+ {
+ if (pkiStatusInfo == null)
+ {
+ throw new IllegalArgumentException("'pkiStatusInfo' cannot be null");
+ }
+
+ this.pkiStatusInfo = pkiStatusInfo;
+ this.errorCode = errorCode;
+ this.errorDetails = errorDetails;
+ }
+
+ public PKIStatusInfo getPKIStatusInfo()
+ {
+ return pkiStatusInfo;
+ }
+
+ public ASN1Integer getErrorCode()
+ {
+ return errorCode;
+ }
+
+ public PKIFreeText getErrorDetails()
+ {
+ 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 ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(pkiStatusInfo);
+ addOptional(v, errorCode);
+ addOptional(v, errorDetails);
+
+ return new DERSequence(v);
+ }
+
+ private void addOptional(ASN1EncodableVector v, ASN1Encodable obj)
+ {
+ if (obj != null)
+ {
+ v.add(obj);
+ }
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/cmp/GenMsgContent.java b/core/src/main/java/org/spongycastle/asn1/cmp/GenMsgContent.java
new file mode 100644
index 00000000..5d65e0d1
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/cmp/GenMsgContent.java
@@ -0,0 +1,71 @@
+package org.spongycastle.asn1.cmp;
+
+import org.spongycastle.asn1.ASN1EncodableVector;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.DERSequence;
+
+public class GenMsgContent
+ extends ASN1Object
+{
+ private ASN1Sequence content;
+
+ private GenMsgContent(ASN1Sequence seq)
+ {
+ content = seq;
+ }
+
+ public static GenMsgContent getInstance(Object o)
+ {
+ if (o instanceof GenMsgContent)
+ {
+ return (GenMsgContent)o;
+ }
+
+ if (o != null)
+ {
+ return new GenMsgContent(ASN1Sequence.getInstance(o));
+ }
+
+ return null;
+ }
+
+ public GenMsgContent(InfoTypeAndValue itv)
+ {
+ content = new DERSequence(itv);
+ }
+
+ public GenMsgContent(InfoTypeAndValue[] itv)
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+ for (int i = 0; i < itv.length; i++)
+ {
+ v.add(itv[i]);
+ }
+ content = new DERSequence(v);
+ }
+
+ public InfoTypeAndValue[] toInfoTypeAndValueArray()
+ {
+ InfoTypeAndValue[] result = new InfoTypeAndValue[content.size()];
+
+ for (int i = 0; i != result.length; i++)
+ {
+ result[i] = InfoTypeAndValue.getInstance(content.getObjectAt(i));
+ }
+
+ return result;
+ }
+
+ /**
+ * <pre>
+ * GenMsgContent ::= SEQUENCE OF InfoTypeAndValue
+ * </pre>
+ * @return a basic ASN.1 object representation.
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ return content;
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/cmp/GenRepContent.java b/core/src/main/java/org/spongycastle/asn1/cmp/GenRepContent.java
new file mode 100644
index 00000000..a6a2f4db
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/cmp/GenRepContent.java
@@ -0,0 +1,71 @@
+package org.spongycastle.asn1.cmp;
+
+import org.spongycastle.asn1.ASN1EncodableVector;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.DERSequence;
+
+public class GenRepContent
+ extends ASN1Object
+{
+ private ASN1Sequence content;
+
+ private GenRepContent(ASN1Sequence seq)
+ {
+ content = seq;
+ }
+
+ public static GenRepContent getInstance(Object o)
+ {
+ if (o instanceof GenRepContent)
+ {
+ return (GenRepContent)o;
+ }
+
+ if (o != null)
+ {
+ return new GenRepContent(ASN1Sequence.getInstance(o));
+ }
+
+ return null;
+ }
+
+ public GenRepContent(InfoTypeAndValue itv)
+ {
+ content = new DERSequence(itv);
+ }
+
+ public GenRepContent(InfoTypeAndValue[] itv)
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+ for (int i = 0; i < itv.length; i++)
+ {
+ v.add(itv[i]);
+ }
+ content = new DERSequence(v);
+ }
+
+ public InfoTypeAndValue[] toInfoTypeAndValueArray()
+ {
+ InfoTypeAndValue[] result = new InfoTypeAndValue[content.size()];
+
+ for (int i = 0; i != result.length; i++)
+ {
+ result[i] = InfoTypeAndValue.getInstance(content.getObjectAt(i));
+ }
+
+ return result;
+ }
+
+ /**
+ * <pre>
+ * GenRepContent ::= SEQUENCE OF InfoTypeAndValue
+ * </pre>
+ * @return a basic ASN.1 object representation.
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ return content;
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/cmp/InfoTypeAndValue.java b/core/src/main/java/org/spongycastle/asn1/cmp/InfoTypeAndValue.java
new file mode 100644
index 00000000..3f99d1e1
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/cmp/InfoTypeAndValue.java
@@ -0,0 +1,132 @@
+package org.spongycastle.asn1.cmp;
+
+import org.spongycastle.asn1.ASN1Encodable;
+import org.spongycastle.asn1.ASN1EncodableVector;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1ObjectIdentifier;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.DERSequence;
+
+/**
+ * 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
+ extends ASN1Object
+{
+ private ASN1ObjectIdentifier infoType;
+ private ASN1Encodable infoValue;
+
+ private InfoTypeAndValue(ASN1Sequence seq)
+ {
+ infoType = ASN1ObjectIdentifier.getInstance(seq.getObjectAt(0));
+
+ if (seq.size() > 1)
+ {
+ infoValue = (ASN1Encodable)seq.getObjectAt(1);
+ }
+ }
+
+ public static InfoTypeAndValue getInstance(Object o)
+ {
+ if (o instanceof InfoTypeAndValue)
+ {
+ return (InfoTypeAndValue)o;
+ }
+
+ if (o != null)
+ {
+ return new InfoTypeAndValue(ASN1Sequence.getInstance(o));
+ }
+
+ return null;
+ }
+
+ public InfoTypeAndValue(
+ ASN1ObjectIdentifier infoType)
+ {
+ this.infoType = infoType;
+ this.infoValue = null;
+ }
+
+ public InfoTypeAndValue(
+ ASN1ObjectIdentifier infoType,
+ ASN1Encodable optionalValue)
+ {
+ this.infoType = infoType;
+ this.infoValue = optionalValue;
+ }
+
+ public ASN1ObjectIdentifier getInfoType()
+ {
+ return infoType;
+ }
+
+ public ASN1Encodable getInfoValue()
+ {
+ return infoValue;
+ }
+
+ /**
+ * <pre>
+ * InfoTypeAndValue ::= SEQUENCE {
+ * infoType OBJECT IDENTIFIER,
+ * infoValue ANY DEFINED BY infoType OPTIONAL
+ * }
+ * </pre>
+ * @return a basic ASN.1 object representation.
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(infoType);
+
+ if (infoValue != null)
+ {
+ v.add(infoValue);
+ }
+
+ return new DERSequence(v);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/cmp/KeyRecRepContent.java b/core/src/main/java/org/spongycastle/asn1/cmp/KeyRecRepContent.java
new file mode 100644
index 00000000..903352e5
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/cmp/KeyRecRepContent.java
@@ -0,0 +1,142 @@
+package org.spongycastle.asn1.cmp;
+
+import java.util.Enumeration;
+
+import org.spongycastle.asn1.ASN1Encodable;
+import org.spongycastle.asn1.ASN1EncodableVector;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.ASN1TaggedObject;
+import org.spongycastle.asn1.DERSequence;
+import org.spongycastle.asn1.DERTaggedObject;
+
+public class KeyRecRepContent
+ extends ASN1Object
+{
+ private PKIStatusInfo status;
+ private CMPCertificate newSigCert;
+ private ASN1Sequence caCerts;
+ private ASN1Sequence keyPairHist;
+
+ private KeyRecRepContent(ASN1Sequence seq)
+ {
+ Enumeration en = seq.getObjects();
+
+ status = PKIStatusInfo.getInstance(en.nextElement());
+
+ while (en.hasMoreElements())
+ {
+ ASN1TaggedObject tObj = ASN1TaggedObject.getInstance(en.nextElement());
+
+ switch (tObj.getTagNo())
+ {
+ 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 IllegalArgumentException("unknown tag number: " + tObj.getTagNo());
+ }
+ }
+ }
+
+ public static KeyRecRepContent getInstance(Object o)
+ {
+ if (o instanceof KeyRecRepContent)
+ {
+ return (KeyRecRepContent)o;
+ }
+
+ if (o != null)
+ {
+ return new KeyRecRepContent(ASN1Sequence.getInstance(o));
+ }
+
+ return null;
+ }
+
+
+ public PKIStatusInfo getStatus()
+ {
+ return status;
+ }
+
+ public CMPCertificate getNewSigCert()
+ {
+ return newSigCert;
+ }
+
+ public CMPCertificate[] getCaCerts()
+ {
+ if (caCerts == null)
+ {
+ return null;
+ }
+
+ CMPCertificate[] results = new CMPCertificate[caCerts.size()];
+
+ for (int i = 0; i != results.length; i++)
+ {
+ results[i] = CMPCertificate.getInstance(caCerts.getObjectAt(i));
+ }
+
+ return results;
+ }
+
+ public CertifiedKeyPair[] getKeyPairHist()
+ {
+ if (keyPairHist == null)
+ {
+ return null;
+ }
+
+ CertifiedKeyPair[] results = new CertifiedKeyPair[keyPairHist.size()];
+
+ for (int i = 0; i != results.length; i++)
+ {
+ results[i] = CertifiedKeyPair.getInstance(keyPairHist.getObjectAt(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 ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(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/core/src/main/java/org/spongycastle/asn1/cmp/OOBCertHash.java b/core/src/main/java/org/spongycastle/asn1/cmp/OOBCertHash.java
new file mode 100644
index 00000000..dc81e7ec
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/cmp/OOBCertHash.java
@@ -0,0 +1,117 @@
+package org.spongycastle.asn1.cmp;
+
+import org.spongycastle.asn1.ASN1Encodable;
+import org.spongycastle.asn1.ASN1EncodableVector;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.ASN1TaggedObject;
+import org.spongycastle.asn1.DERBitString;
+import org.spongycastle.asn1.DERSequence;
+import org.spongycastle.asn1.DERTaggedObject;
+import org.spongycastle.asn1.crmf.CertId;
+import org.spongycastle.asn1.x509.AlgorithmIdentifier;
+
+public class OOBCertHash
+ extends ASN1Object
+{
+ private AlgorithmIdentifier hashAlg;
+ private CertId certId;
+ private DERBitString hashVal;
+
+ private OOBCertHash(ASN1Sequence seq)
+ {
+ int index = seq.size() - 1;
+
+ hashVal = DERBitString.getInstance(seq.getObjectAt(index--));
+
+ for (int i = index; i >= 0; i--)
+ {
+ ASN1TaggedObject tObj = (ASN1TaggedObject)seq.getObjectAt(i);
+
+ if (tObj.getTagNo() == 0)
+ {
+ hashAlg = AlgorithmIdentifier.getInstance(tObj, true);
+ }
+ else
+ {
+ certId = CertId.getInstance(tObj, true);
+ }
+ }
+
+ }
+
+ public static OOBCertHash getInstance(Object o)
+ {
+ if (o instanceof OOBCertHash)
+ {
+ return (OOBCertHash)o;
+ }
+
+ if (o != null)
+ {
+ return new OOBCertHash(ASN1Sequence.getInstance(o));
+ }
+
+ return null;
+ }
+
+ public OOBCertHash(AlgorithmIdentifier hashAlg, CertId certId, byte[] hashVal)
+ {
+ this(hashAlg, certId, new DERBitString(hashVal));
+ }
+
+ public OOBCertHash(AlgorithmIdentifier hashAlg, CertId certId, DERBitString hashVal)
+ {
+ this.hashAlg = hashAlg;
+ this.certId = certId;
+ this.hashVal = hashVal;
+ }
+
+ public AlgorithmIdentifier getHashAlg()
+ {
+ return hashAlg;
+ }
+
+ public CertId getCertId()
+ {
+ return certId;
+ }
+
+ public DERBitString getHashVal()
+ {
+ return hashVal;
+ }
+
+ /**
+ * <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 ASN1Primitive toASN1Primitive()
+ {
+ 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/core/src/main/java/org/spongycastle/asn1/cmp/PBMParameter.java b/core/src/main/java/org/spongycastle/asn1/cmp/PBMParameter.java
new file mode 100644
index 00000000..83c443cf
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/cmp/PBMParameter.java
@@ -0,0 +1,117 @@
+package org.spongycastle.asn1.cmp;
+
+import org.spongycastle.asn1.ASN1EncodableVector;
+import org.spongycastle.asn1.ASN1Integer;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1OctetString;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.DEROctetString;
+import org.spongycastle.asn1.DERSequence;
+import org.spongycastle.asn1.x509.AlgorithmIdentifier;
+
+public class PBMParameter
+ extends ASN1Object
+{
+ private ASN1OctetString salt;
+ private AlgorithmIdentifier owf;
+ private ASN1Integer iterationCount;
+ private AlgorithmIdentifier mac;
+
+ private PBMParameter(ASN1Sequence seq)
+ {
+ salt = ASN1OctetString.getInstance(seq.getObjectAt(0));
+ owf = AlgorithmIdentifier.getInstance(seq.getObjectAt(1));
+ iterationCount = ASN1Integer.getInstance(seq.getObjectAt(2));
+ mac = AlgorithmIdentifier.getInstance(seq.getObjectAt(3));
+ }
+
+ public static PBMParameter getInstance(Object o)
+ {
+ if (o instanceof PBMParameter)
+ {
+ return (PBMParameter)o;
+ }
+
+ if (o != null)
+ {
+ return new PBMParameter(ASN1Sequence.getInstance(o));
+ }
+
+ return null;
+ }
+
+ public PBMParameter(
+ byte[] salt,
+ AlgorithmIdentifier owf,
+ int iterationCount,
+ AlgorithmIdentifier mac)
+ {
+ this(new DEROctetString(salt), owf,
+ new ASN1Integer(iterationCount), mac);
+ }
+
+ public PBMParameter(
+ ASN1OctetString salt,
+ AlgorithmIdentifier owf,
+ ASN1Integer iterationCount,
+ AlgorithmIdentifier mac)
+ {
+ this.salt = salt;
+ this.owf = owf;
+ this.iterationCount = iterationCount;
+ this.mac = mac;
+ }
+
+ public ASN1OctetString getSalt()
+ {
+ return salt;
+ }
+
+ public AlgorithmIdentifier getOwf()
+ {
+ return owf;
+ }
+
+ public ASN1Integer getIterationCount()
+ {
+ return iterationCount;
+ }
+
+ public AlgorithmIdentifier getMac()
+ {
+ 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 ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(salt);
+ v.add(owf);
+ v.add(iterationCount);
+ v.add(mac);
+
+ return new DERSequence(v);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/cmp/PKIBody.java b/core/src/main/java/org/spongycastle/asn1/cmp/PKIBody.java
new file mode 100644
index 00000000..95b6a11c
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/cmp/PKIBody.java
@@ -0,0 +1,194 @@
+package org.spongycastle.asn1.cmp;
+
+import org.spongycastle.asn1.ASN1Choice;
+import org.spongycastle.asn1.ASN1Encodable;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1TaggedObject;
+import org.spongycastle.asn1.DERTaggedObject;
+import org.spongycastle.asn1.crmf.CertReqMessages;
+import org.spongycastle.asn1.pkcs.CertificationRequest;
+
+public class PKIBody
+ extends ASN1Object
+ implements ASN1Choice
+{
+ public static final int TYPE_INIT_REQ = 0;
+ public static final int TYPE_INIT_REP = 1;
+ public static final int TYPE_CERT_REQ = 2;
+ public static final int TYPE_CERT_REP = 3;
+ public static final int TYPE_P10_CERT_REQ = 4;
+ public static final int TYPE_POPO_CHALL = 5;
+ public static final int TYPE_POPO_REP = 6;
+ public static final int TYPE_KEY_UPDATE_REQ = 7;
+ public static final int TYPE_KEY_UPDATE_REP = 8;
+ public static final int TYPE_KEY_RECOVERY_REQ = 9;
+ public static final int TYPE_KEY_RECOVERY_REP = 10;
+ public static final int TYPE_REVOCATION_REQ = 11;
+ public static final int TYPE_REVOCATION_REP = 12;
+ public static final int TYPE_CROSS_CERT_REQ = 13;
+ public static final int TYPE_CROSS_CERT_REP = 14;
+ public static final int TYPE_CA_KEY_UPDATE_ANN = 15;
+ public static final int TYPE_CERT_ANN = 16;
+ public static final int TYPE_REVOCATION_ANN = 17;
+ public static final int TYPE_CRL_ANN = 18;
+ public static final int TYPE_CONFIRM = 19;
+ public static final int TYPE_NESTED = 20;
+ public static final int TYPE_GEN_MSG = 21;
+ public static final int TYPE_GEN_REP = 22;
+ public static final int TYPE_ERROR = 23;
+ public static final int TYPE_CERT_CONFIRM = 24;
+ public static final int TYPE_POLL_REQ = 25;
+ public static final int TYPE_POLL_REP = 26;
+
+ private int tagNo;
+ private ASN1Encodable body;
+
+ public static PKIBody getInstance(Object o)
+ {
+ if (o == null || o instanceof PKIBody)
+ {
+ return (PKIBody)o;
+ }
+
+ if (o instanceof ASN1TaggedObject)
+ {
+ return new PKIBody((ASN1TaggedObject)o);
+ }
+
+ throw new IllegalArgumentException("Invalid object: " + o.getClass().getName());
+ }
+
+ private PKIBody(ASN1TaggedObject tagged)
+ {
+ tagNo = tagged.getTagNo();
+ 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 IllegalArgumentException("unknown tag number: " + type);
+ }
+ }
+
+ public int getType()
+ {
+ return tagNo;
+ }
+
+ public ASN1Encodable getContent()
+ {
+ 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 ASN1Primitive toASN1Primitive()
+ {
+ return new DERTaggedObject(true, tagNo, body);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/cmp/PKIConfirmContent.java b/core/src/main/java/org/spongycastle/asn1/cmp/PKIConfirmContent.java
new file mode 100644
index 00000000..4019779f
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/cmp/PKIConfirmContent.java
@@ -0,0 +1,48 @@
+package org.spongycastle.asn1.cmp;
+
+import org.spongycastle.asn1.ASN1Null;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.DERNull;
+
+public class PKIConfirmContent
+ extends ASN1Object
+{
+ private ASN1Null val;
+
+ private PKIConfirmContent(ASN1Null val)
+ {
+ this.val = val;
+ }
+
+ public static PKIConfirmContent getInstance(Object o)
+ {
+ if (o == null || o instanceof PKIConfirmContent)
+ {
+ return (PKIConfirmContent)o;
+ }
+
+ if (o instanceof ASN1Null)
+ {
+ return new PKIConfirmContent((ASN1Null)o);
+ }
+
+ throw new IllegalArgumentException("Invalid object: " + o.getClass().getName());
+ }
+
+ public PKIConfirmContent()
+ {
+ val = DERNull.INSTANCE;
+ }
+
+ /**
+ * <pre>
+ * PKIConfirmContent ::= NULL
+ * </pre>
+ * @return a basic ASN.1 object representation.
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ return val;
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/cmp/PKIFailureInfo.java b/core/src/main/java/org/spongycastle/asn1/cmp/PKIFailureInfo.java
new file mode 100644
index 00000000..03dd5574
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/cmp/PKIFailureInfo.java
@@ -0,0 +1,126 @@
+package org.spongycastle.asn1.cmp;
+
+import org.spongycastle.asn1.DERBitString;
+
+/**
+ * <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
+ * certRevoked (10),
+ * certConfirmed (11),
+ * wrongIntegrity (12),
+ * badRecipientNonce (13),
+ * 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
+ * badSenderNonce (18),
+ * badCertTemplate (19),
+ * signerNotTrusted (20),
+ * transactionIdInUse (21),
+ * unsupportedVersion (22),
+ * notAuthorized (23),
+ * systemUnavail (24),
+ * systemFailure (25),
+ * -- the request cannot be handled due to system failure
+ * duplicateCertReq (26)
+ * </pre>
+ */
+public class PKIFailureInfo
+ extends DERBitString
+{
+ public static final int badAlg = (1 << 7); // unrecognized or unsupported Algorithm Identifier
+ public static final int badMessageCheck = (1 << 6); // integrity check failed (e.g., signature did not verify)
+ public static final int badRequest = (1 << 5);
+ public static final int badTime = (1 << 4); // -- messageTime was not sufficiently close to the system time, as defined by local policy
+ public static final int badCertId = (1 << 3); // no certificate could be found matching the provided criteria
+ public static final int badDataFormat = (1 << 2);
+ public static final int wrongAuthority = (1 << 1); // the authority indicated in the request is different from the one creating the response token
+ public static final int incorrectData = 1; // the requester's data is incorrect (for notary services)
+ public static final int missingTimeStamp = (1 << 15); // when the timestamp is missing but should be there (by policy)
+ public static final int badPOP = (1 << 14); // the proof-of-possession failed
+ public static final int certRevoked = (1 << 13);
+ public static final int certConfirmed = (1 << 12);
+ public static final int wrongIntegrity = (1 << 11);
+ public static final int badRecipientNonce = (1 << 10);
+ public static final int timeNotAvailable = (1 << 9); // the TSA's time source is not available
+ public static final int unacceptedPolicy = (1 << 8); // the requested TSA policy is not supported by the TSA
+ public static final int unacceptedExtension = (1 << 23); //the requested extension is not supported by the TSA
+ public static final int addInfoNotAvailable = (1 << 22); //the additional information requested could not be understood or is not available
+ public static final int badSenderNonce = (1 << 21);
+ public static final int badCertTemplate = (1 << 20);
+ public static final int signerNotTrusted = (1 << 19);
+ public static final int transactionIdInUse = (1 << 18);
+ public static final int unsupportedVersion = (1 << 17);
+ public static final int notAuthorized = (1 << 16);
+ public static final int systemUnavail = (1 << 31);
+ public static final int systemFailure = (1 << 30); //the request cannot be handled due to system failure
+ public static final int duplicateCertReq = (1 << 29);
+
+ /** @deprecated use lower case version */
+ public static final int BAD_ALG = badAlg; // unrecognized or unsupported Algorithm Identifier
+ /** @deprecated use lower case version */
+ public static final int BAD_MESSAGE_CHECK = badMessageCheck;
+ /** @deprecated use lower case version */
+ public static final int BAD_REQUEST = badRequest; // transaction not permitted or supported
+ /** @deprecated use lower case version */
+ public static final int BAD_TIME = badTime;
+ /** @deprecated use lower case version */
+ public static final int BAD_CERT_ID = badCertId;
+ /** @deprecated use lower case version */
+ public static final int BAD_DATA_FORMAT = badDataFormat; // the data submitted has the wrong format
+ /** @deprecated use lower case version */
+ public static final int WRONG_AUTHORITY = wrongAuthority;
+ /** @deprecated use lower case version */
+ public static final int INCORRECT_DATA = incorrectData;
+ /** @deprecated use lower case version */
+ public static final int MISSING_TIME_STAMP = missingTimeStamp;
+ /** @deprecated use lower case version */
+ public static final int BAD_POP = badPOP;
+ /** @deprecated use lower case version */
+ public static final int TIME_NOT_AVAILABLE = timeNotAvailable;
+ /** @deprecated use lower case version */
+ public static final int UNACCEPTED_POLICY = unacceptedPolicy;
+ /** @deprecated use lower case version */
+ public static final int UNACCEPTED_EXTENSION = unacceptedExtension;
+ /** @deprecated use lower case version */
+ public static final int ADD_INFO_NOT_AVAILABLE = addInfoNotAvailable;
+ /** @deprecated use lower case version */
+ public static final int SYSTEM_FAILURE = systemFailure;
+ /**
+ * Basic constructor.
+ */
+ public PKIFailureInfo(
+ int info)
+ {
+ super(getBytes(info), getPadBits(info));
+ }
+
+ public PKIFailureInfo(
+ DERBitString info)
+ {
+ super(info.getBytes(), info.getPadBits());
+ }
+
+ public String toString()
+ {
+ return "PKIFailureInfo: 0x" + Integer.toHexString(this.intValue());
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/cmp/PKIFreeText.java b/core/src/main/java/org/spongycastle/asn1/cmp/PKIFreeText.java
new file mode 100644
index 00000000..8a10714f
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/cmp/PKIFreeText.java
@@ -0,0 +1,115 @@
+package org.spongycastle.asn1.cmp;
+
+import java.util.Enumeration;
+
+import org.spongycastle.asn1.ASN1EncodableVector;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.ASN1TaggedObject;
+import org.spongycastle.asn1.DERSequence;
+import org.spongycastle.asn1.DERUTF8String;
+
+public class PKIFreeText
+ extends ASN1Object
+{
+ ASN1Sequence strings;
+
+ public static PKIFreeText getInstance(
+ ASN1TaggedObject obj,
+ boolean explicit)
+ {
+ return getInstance(ASN1Sequence.getInstance(obj, explicit));
+ }
+
+ public static PKIFreeText getInstance(
+ Object obj)
+ {
+ if (obj instanceof PKIFreeText)
+ {
+ return (PKIFreeText)obj;
+ }
+ else if (obj != null)
+ {
+ return new PKIFreeText(ASN1Sequence.getInstance(obj));
+ }
+
+ return null;
+ }
+
+ private PKIFreeText(
+ ASN1Sequence seq)
+ {
+ Enumeration e = seq.getObjects();
+ while (e.hasMoreElements())
+ {
+ if (!(e.nextElement() instanceof DERUTF8String))
+ {
+ throw new IllegalArgumentException("attempt to insert non UTF8 STRING into PKIFreeText");
+ }
+ }
+
+ strings = seq;
+ }
+
+ public PKIFreeText(
+ DERUTF8String p)
+ {
+ strings = new DERSequence(p);
+ }
+
+ public PKIFreeText(
+ String p)
+ {
+ this(new DERUTF8String(p));
+ }
+
+ public PKIFreeText(
+ DERUTF8String[] strs)
+ {
+ strings = new DERSequence(strs);
+ }
+
+ public PKIFreeText(
+ String[] strs)
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+ for (int i = 0; i < strs.length; i++)
+ {
+ v.add(new DERUTF8String(strs[i]));
+ }
+ strings = new DERSequence(v);
+ }
+
+ /**
+ * Return the number of string elements present.
+ *
+ * @return number of elements present.
+ */
+ public int size()
+ {
+ return strings.size();
+ }
+
+ /**
+ * Return the UTF8STRING at index i.
+ *
+ * @param i index of the string of interest
+ * @return the string at index i.
+ */
+ public DERUTF8String getStringAt(
+ int i)
+ {
+ return (DERUTF8String)strings.getObjectAt(i);
+ }
+
+ /**
+ * <pre>
+ * PKIFreeText ::= SEQUENCE SIZE (1..MAX) OF UTF8String
+ * </pre>
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ return strings;
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/cmp/PKIHeader.java b/core/src/main/java/org/spongycastle/asn1/cmp/PKIHeader.java
new file mode 100644
index 00000000..afcd7767
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/cmp/PKIHeader.java
@@ -0,0 +1,260 @@
+package org.spongycastle.asn1.cmp;
+
+import java.util.Enumeration;
+
+import org.spongycastle.asn1.ASN1Encodable;
+import org.spongycastle.asn1.ASN1EncodableVector;
+import org.spongycastle.asn1.ASN1GeneralizedTime;
+import org.spongycastle.asn1.ASN1Integer;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1OctetString;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.ASN1TaggedObject;
+import org.spongycastle.asn1.DERSequence;
+import org.spongycastle.asn1.DERTaggedObject;
+import org.spongycastle.asn1.x500.X500Name;
+import org.spongycastle.asn1.x509.AlgorithmIdentifier;
+import org.spongycastle.asn1.x509.GeneralName;
+
+public class PKIHeader
+ extends ASN1Object
+{
+ /**
+ * Value for a "null" recipient or sender.
+ */
+ public static final GeneralName NULL_NAME = new GeneralName(X500Name.getInstance(new DERSequence()));
+
+ public static final int CMP_1999 = 1;
+ public static final int CMP_2000 = 2;
+
+ private ASN1Integer pvno;
+ private GeneralName sender;
+ private GeneralName recipient;
+ private ASN1GeneralizedTime 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;
+
+ private PKIHeader(ASN1Sequence seq)
+ {
+ Enumeration en = seq.getObjects();
+
+ pvno = ASN1Integer.getInstance(en.nextElement());
+ sender = GeneralName.getInstance(en.nextElement());
+ recipient = GeneralName.getInstance(en.nextElement());
+
+ while (en.hasMoreElements())
+ {
+ ASN1TaggedObject tObj = (ASN1TaggedObject)en.nextElement();
+
+ switch (tObj.getTagNo())
+ {
+ case 0:
+ messageTime = ASN1GeneralizedTime.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 IllegalArgumentException("unknown tag number: " + tObj.getTagNo());
+ }
+ }
+ }
+
+ public static PKIHeader getInstance(Object o)
+ {
+ if (o instanceof PKIHeader)
+ {
+ return (PKIHeader)o;
+ }
+
+ if (o != null)
+ {
+ return new PKIHeader(ASN1Sequence.getInstance(o));
+ }
+
+ return null;
+ }
+
+ public PKIHeader(
+ int pvno,
+ GeneralName sender,
+ GeneralName recipient)
+ {
+ this(new ASN1Integer(pvno), sender, recipient);
+ }
+
+ private PKIHeader(
+ ASN1Integer pvno,
+ GeneralName sender,
+ GeneralName recipient)
+ {
+ this.pvno = pvno;
+ this.sender = sender;
+ this.recipient = recipient;
+ }
+
+ public ASN1Integer getPvno()
+ {
+ return pvno;
+ }
+
+ public GeneralName getSender()
+ {
+ return sender;
+ }
+
+ public GeneralName getRecipient()
+ {
+ return recipient;
+ }
+
+ public ASN1GeneralizedTime getMessageTime()
+ {
+ return messageTime;
+ }
+
+ public AlgorithmIdentifier getProtectionAlg()
+ {
+ return protectionAlg;
+ }
+
+ public ASN1OctetString getSenderKID()
+ {
+ return senderKID;
+ }
+
+ public ASN1OctetString getRecipKID()
+ {
+ return recipKID;
+ }
+
+ public ASN1OctetString getTransactionID()
+ {
+ return transactionID;
+ }
+
+ public ASN1OctetString getSenderNonce()
+ {
+ return senderNonce;
+ }
+
+ public ASN1OctetString getRecipNonce()
+ {
+ return recipNonce;
+ }
+
+ public PKIFreeText getFreeText()
+ {
+ return freeText;
+ }
+
+ public InfoTypeAndValue[] getGeneralInfo()
+ {
+ if (generalInfo == null)
+ {
+ return null;
+ }
+ InfoTypeAndValue[] results = new InfoTypeAndValue[generalInfo.size()];
+ for (int i = 0; i < results.length; i++)
+ {
+ results[i]
+ = InfoTypeAndValue.getInstance(generalInfo.getObjectAt(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 ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(pvno);
+ v.add(sender);
+ v.add(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 void addOptional(ASN1EncodableVector v, int tagNo, ASN1Encodable obj)
+ {
+ if (obj != null)
+ {
+ v.add(new DERTaggedObject(true, tagNo, obj));
+ }
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/cmp/PKIHeaderBuilder.java b/core/src/main/java/org/spongycastle/asn1/cmp/PKIHeaderBuilder.java
new file mode 100644
index 00000000..5249c5e0
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/cmp/PKIHeaderBuilder.java
@@ -0,0 +1,243 @@
+package org.spongycastle.asn1.cmp;
+
+import org.spongycastle.asn1.ASN1Encodable;
+import org.spongycastle.asn1.ASN1EncodableVector;
+import org.spongycastle.asn1.ASN1GeneralizedTime;
+import org.spongycastle.asn1.ASN1Integer;
+import org.spongycastle.asn1.ASN1OctetString;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.DEROctetString;
+import org.spongycastle.asn1.DERSequence;
+import org.spongycastle.asn1.DERTaggedObject;
+import org.spongycastle.asn1.x509.AlgorithmIdentifier;
+import org.spongycastle.asn1.x509.GeneralName;
+
+public class PKIHeaderBuilder
+{
+ private ASN1Integer pvno;
+ private GeneralName sender;
+ private GeneralName recipient;
+ private ASN1GeneralizedTime 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 ASN1Integer(pvno), sender, recipient);
+ }
+
+ private PKIHeaderBuilder(
+ ASN1Integer pvno,
+ GeneralName sender,
+ GeneralName recipient)
+ {
+ this.pvno = pvno;
+ this.sender = sender;
+ this.recipient = recipient;
+ }
+
+ public PKIHeaderBuilder setMessageTime(ASN1GeneralizedTime time)
+ {
+ messageTime = time;
+
+ return this;
+ }
+
+ public PKIHeaderBuilder setProtectionAlg(AlgorithmIdentifier aid)
+ {
+ protectionAlg = aid;
+
+ return this;
+ }
+
+ public PKIHeaderBuilder setSenderKID(byte[] kid)
+ {
+ return setSenderKID(kid == null ? null : new DEROctetString(kid));
+ }
+
+ public PKIHeaderBuilder setSenderKID(ASN1OctetString kid)
+ {
+ senderKID = kid;
+
+ return this;
+ }
+
+ public PKIHeaderBuilder setRecipKID(byte[] kid)
+ {
+ return setRecipKID(kid == null ? null : new DEROctetString(kid));
+ }
+
+ public PKIHeaderBuilder setRecipKID(DEROctetString kid)
+ {
+ recipKID = kid;
+
+ return this;
+ }
+
+ public PKIHeaderBuilder setTransactionID(byte[] tid)
+ {
+ return setTransactionID(tid == null ? null : new DEROctetString(tid));
+ }
+
+ public PKIHeaderBuilder setTransactionID(ASN1OctetString tid)
+ {
+ transactionID = tid;
+
+ return this;
+ }
+
+ public PKIHeaderBuilder setSenderNonce(byte[] nonce)
+ {
+ return setSenderNonce(nonce == null ? null : new DEROctetString(nonce));
+ }
+
+ public PKIHeaderBuilder setSenderNonce(ASN1OctetString nonce)
+ {
+ senderNonce = nonce;
+
+ return this;
+ }
+
+ public PKIHeaderBuilder setRecipNonce(byte[] nonce)
+ {
+ return setRecipNonce(nonce == null ? null : new DEROctetString(nonce));
+ }
+
+ public PKIHeaderBuilder setRecipNonce(ASN1OctetString nonce)
+ {
+ recipNonce = nonce;
+
+ return this;
+ }
+
+ public PKIHeaderBuilder setFreeText(PKIFreeText text)
+ {
+ freeText = text;
+
+ return this;
+ }
+
+ public PKIHeaderBuilder setGeneralInfo(InfoTypeAndValue genInfo)
+ {
+ return setGeneralInfo(makeGeneralInfoSeq(genInfo));
+ }
+
+ public PKIHeaderBuilder setGeneralInfo(InfoTypeAndValue[] genInfos)
+ {
+ return setGeneralInfo(makeGeneralInfoSeq(genInfos));
+ }
+
+ public 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 PKIHeader build()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(pvno);
+ v.add(sender);
+ v.add(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/core/src/main/java/org/spongycastle/asn1/cmp/PKIMessage.java b/core/src/main/java/org/spongycastle/asn1/cmp/PKIMessage.java
new file mode 100644
index 00000000..fbb4dfe7
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/cmp/PKIMessage.java
@@ -0,0 +1,166 @@
+package org.spongycastle.asn1.cmp;
+
+import java.util.Enumeration;
+
+import org.spongycastle.asn1.ASN1Encodable;
+import org.spongycastle.asn1.ASN1EncodableVector;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.ASN1TaggedObject;
+import org.spongycastle.asn1.DERBitString;
+import org.spongycastle.asn1.DERSequence;
+import org.spongycastle.asn1.DERTaggedObject;
+
+public class PKIMessage
+ extends ASN1Object
+{
+ private PKIHeader header;
+ private PKIBody body;
+ private DERBitString protection;
+ private ASN1Sequence extraCerts;
+
+ private PKIMessage(ASN1Sequence seq)
+ {
+ Enumeration en = seq.getObjects();
+
+ header = PKIHeader.getInstance(en.nextElement());
+ body = PKIBody.getInstance(en.nextElement());
+
+ while (en.hasMoreElements())
+ {
+ ASN1TaggedObject tObj = (ASN1TaggedObject)en.nextElement();
+
+ if (tObj.getTagNo() == 0)
+ {
+ protection = DERBitString.getInstance(tObj, true);
+ }
+ else
+ {
+ extraCerts = ASN1Sequence.getInstance(tObj, true);
+ }
+ }
+ }
+
+ public static PKIMessage getInstance(Object o)
+ {
+ if (o instanceof PKIMessage)
+ {
+ return (PKIMessage)o;
+ }
+ else if (o != null)
+ {
+ return new PKIMessage(ASN1Sequence.getInstance(o));
+ }
+
+ 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)
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+ for (int i = 0; i < extraCerts.length; i++)
+ {
+ v.add(extraCerts[i]);
+ }
+ this.extraCerts = new DERSequence(v);
+ }
+ }
+
+ 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 PKIHeader getHeader()
+ {
+ return header;
+ }
+
+ public PKIBody getBody()
+ {
+ return body;
+ }
+
+ public DERBitString getProtection()
+ {
+ return protection;
+ }
+
+ public CMPCertificate[] getExtraCerts()
+ {
+ if (extraCerts == null)
+ {
+ return null;
+ }
+
+ CMPCertificate[] results = new CMPCertificate[extraCerts.size()];
+
+ for (int i = 0; i < results.length; i++)
+ {
+ results[i] = CMPCertificate.getInstance(extraCerts.getObjectAt(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 ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(header);
+ v.add(body);
+
+ addOptional(v, 0, protection);
+ addOptional(v, 1, extraCerts);
+
+ 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/core/src/main/java/org/spongycastle/asn1/cmp/PKIMessages.java b/core/src/main/java/org/spongycastle/asn1/cmp/PKIMessages.java
new file mode 100644
index 00000000..33b47323
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/cmp/PKIMessages.java
@@ -0,0 +1,71 @@
+package org.spongycastle.asn1.cmp;
+
+import org.spongycastle.asn1.ASN1EncodableVector;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.DERSequence;
+
+public class PKIMessages
+ extends ASN1Object
+{
+ private ASN1Sequence content;
+
+ private PKIMessages(ASN1Sequence seq)
+ {
+ content = seq;
+ }
+
+ public static PKIMessages getInstance(Object o)
+ {
+ if (o instanceof PKIMessages)
+ {
+ return (PKIMessages)o;
+ }
+
+ if (o != null)
+ {
+ return new PKIMessages(ASN1Sequence.getInstance(o));
+ }
+
+ return null;
+ }
+
+ public PKIMessages(PKIMessage msg)
+ {
+ content = new DERSequence(msg);
+ }
+
+ public PKIMessages(PKIMessage[] msgs)
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+ for (int i = 0; i < msgs.length; i++)
+ {
+ v.add(msgs[i]);
+ }
+ content = new DERSequence(v);
+ }
+
+ public PKIMessage[] toPKIMessageArray()
+ {
+ PKIMessage[] result = new PKIMessage[content.size()];
+
+ for (int i = 0; i != result.length; i++)
+ {
+ result[i] = PKIMessage.getInstance(content.getObjectAt(i));
+ }
+
+ return result;
+ }
+
+ /**
+ * <pre>
+ * PKIMessages ::= SEQUENCE SIZE (1..MAX) OF PKIMessage
+ * </pre>
+ * @return a basic ASN.1 object representation.
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ return content;
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/cmp/PKIStatus.java b/core/src/main/java/org/spongycastle/asn1/cmp/PKIStatus.java
new file mode 100644
index 00000000..af4235f1
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/cmp/PKIStatus.java
@@ -0,0 +1,64 @@
+package org.spongycastle.asn1.cmp;
+
+import java.math.BigInteger;
+
+import org.spongycastle.asn1.ASN1Integer;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1Primitive;
+
+public class PKIStatus
+ extends ASN1Object
+{
+ public static final int GRANTED = 0;
+ public static final int GRANTED_WITH_MODS = 1;
+ public static final int REJECTION = 2;
+ public static final int WAITING = 3;
+ public static final int REVOCATION_WARNING = 4;
+ public static final int REVOCATION_NOTIFICATION = 5;
+ public static final int KEY_UPDATE_WARNING = 6;
+
+ public static final PKIStatus granted = new PKIStatus(GRANTED);
+ public static final PKIStatus grantedWithMods = new PKIStatus(GRANTED_WITH_MODS);
+ public static final PKIStatus rejection = new PKIStatus(REJECTION);
+ public static final PKIStatus waiting = new PKIStatus(WAITING);
+ public static final PKIStatus revocationWarning = new PKIStatus(REVOCATION_WARNING);
+ public static final PKIStatus revocationNotification = new PKIStatus(REVOCATION_NOTIFICATION);
+ public static final PKIStatus keyUpdateWaiting = new PKIStatus(KEY_UPDATE_WARNING);
+
+ private ASN1Integer value;
+
+ private PKIStatus(int value)
+ {
+ this(new ASN1Integer(value));
+ }
+
+ private PKIStatus(ASN1Integer value)
+ {
+ this.value = value;
+ }
+
+ public static PKIStatus getInstance(Object o)
+ {
+ if (o instanceof PKIStatus)
+ {
+ return (PKIStatus)o;
+ }
+
+ if (o != null)
+ {
+ return new PKIStatus(ASN1Integer.getInstance(o));
+ }
+
+ return null;
+ }
+
+ public BigInteger getValue()
+ {
+ return value.getValue();
+ }
+
+ public ASN1Primitive toASN1Primitive()
+ {
+ return value;
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/cmp/PKIStatusInfo.java b/core/src/main/java/org/spongycastle/asn1/cmp/PKIStatusInfo.java
new file mode 100644
index 00000000..5deae95f
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/cmp/PKIStatusInfo.java
@@ -0,0 +1,165 @@
+package org.spongycastle.asn1.cmp;
+
+import java.math.BigInteger;
+
+import org.spongycastle.asn1.ASN1EncodableVector;
+import org.spongycastle.asn1.ASN1Integer;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.ASN1TaggedObject;
+import org.spongycastle.asn1.DERBitString;
+import org.spongycastle.asn1.DERSequence;
+
+public class PKIStatusInfo
+ extends ASN1Object
+{
+ ASN1Integer status;
+ PKIFreeText statusString;
+ DERBitString failInfo;
+
+ public static PKIStatusInfo getInstance(
+ ASN1TaggedObject obj,
+ boolean explicit)
+ {
+ return getInstance(ASN1Sequence.getInstance(obj, explicit));
+ }
+
+ public static PKIStatusInfo getInstance(
+ Object obj)
+ {
+ if (obj instanceof PKIStatusInfo)
+ {
+ return (PKIStatusInfo)obj;
+ }
+ else if (obj != null)
+ {
+ return new PKIStatusInfo(ASN1Sequence.getInstance(obj));
+ }
+
+ return null;
+ }
+
+ private PKIStatusInfo(
+ ASN1Sequence seq)
+ {
+ this.status = ASN1Integer.getInstance(seq.getObjectAt(0));
+
+ this.statusString = null;
+ this.failInfo = null;
+
+ if (seq.size() > 2)
+ {
+ this.statusString = PKIFreeText.getInstance(seq.getObjectAt(1));
+ this.failInfo = DERBitString.getInstance(seq.getObjectAt(2));
+ }
+ else if (seq.size() > 1)
+ {
+ Object obj = seq.getObjectAt(1);
+ if (obj instanceof DERBitString)
+ {
+ this.failInfo = DERBitString.getInstance(obj);
+ }
+ else
+ {
+ this.statusString = PKIFreeText.getInstance(obj);
+ }
+ }
+ }
+
+ /**
+ * @param status
+ */
+ public PKIStatusInfo(PKIStatus status)
+ {
+ this.status = ASN1Integer.getInstance(status.toASN1Primitive());
+ }
+
+ /**
+ *
+ * @param status
+ * @param statusString
+ */
+ public PKIStatusInfo(
+ PKIStatus status,
+ PKIFreeText statusString)
+ {
+ this.status = ASN1Integer.getInstance(status.toASN1Primitive());
+ this.statusString = statusString;
+ }
+
+ public PKIStatusInfo(
+ PKIStatus status,
+ PKIFreeText statusString,
+ PKIFailureInfo failInfo)
+ {
+ this.status = ASN1Integer.getInstance(status.toASN1Primitive());
+ this.statusString = statusString;
+ this.failInfo = failInfo;
+ }
+
+ public BigInteger getStatus()
+ {
+ return status.getValue();
+ }
+
+ public PKIFreeText getStatusString()
+ {
+ return statusString;
+ }
+
+ public DERBitString getFailInfo()
+ {
+ 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 ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(status);
+
+ if (statusString != null)
+ {
+ v.add(statusString);
+ }
+
+ if (failInfo!= null)
+ {
+ v.add(failInfo);
+ }
+
+ return new DERSequence(v);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/cmp/POPODecKeyChallContent.java b/core/src/main/java/org/spongycastle/asn1/cmp/POPODecKeyChallContent.java
new file mode 100644
index 00000000..2c636143
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/cmp/POPODecKeyChallContent.java
@@ -0,0 +1,54 @@
+package org.spongycastle.asn1.cmp;
+
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1Sequence;
+
+public class POPODecKeyChallContent
+ extends ASN1Object
+{
+ private ASN1Sequence content;
+
+ private POPODecKeyChallContent(ASN1Sequence seq)
+ {
+ content = seq;
+ }
+
+ public static POPODecKeyChallContent getInstance(Object o)
+ {
+ if (o instanceof POPODecKeyChallContent)
+ {
+ return (POPODecKeyChallContent)o;
+ }
+
+ if (o != null)
+ {
+ return new POPODecKeyChallContent(ASN1Sequence.getInstance(o));
+ }
+
+ return null;
+ }
+
+ public Challenge[] toChallengeArray()
+ {
+ Challenge[] result = new Challenge[content.size()];
+
+ for (int i = 0; i != result.length; i++)
+ {
+ result[i] = Challenge.getInstance(content.getObjectAt(i));
+ }
+
+ return result;
+ }
+
+ /**
+ * <pre>
+ * POPODecKeyChallContent ::= SEQUENCE OF Challenge
+ * </pre>
+ * @return a basic ASN.1 object representation.
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ return content;
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/cmp/POPODecKeyRespContent.java b/core/src/main/java/org/spongycastle/asn1/cmp/POPODecKeyRespContent.java
new file mode 100644
index 00000000..48466b89
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/cmp/POPODecKeyRespContent.java
@@ -0,0 +1,55 @@
+package org.spongycastle.asn1.cmp;
+
+import org.spongycastle.asn1.ASN1Integer;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1Sequence;
+
+public class POPODecKeyRespContent
+ extends ASN1Object
+{
+ private ASN1Sequence content;
+
+ private POPODecKeyRespContent(ASN1Sequence seq)
+ {
+ content = seq;
+ }
+
+ public static POPODecKeyRespContent getInstance(Object o)
+ {
+ if (o instanceof POPODecKeyRespContent)
+ {
+ return (POPODecKeyRespContent)o;
+ }
+
+ if (o != null)
+ {
+ return new POPODecKeyRespContent(ASN1Sequence.getInstance(o));
+ }
+
+ return null;
+ }
+
+ public ASN1Integer[] toASN1IntegerArray()
+ {
+ ASN1Integer[] result = new ASN1Integer[content.size()];
+
+ for (int i = 0; i != result.length; i++)
+ {
+ result[i] = ASN1Integer.getInstance(content.getObjectAt(i));
+ }
+
+ return result;
+ }
+
+ /**
+ * <pre>
+ * POPODecKeyRespContent ::= SEQUENCE OF INTEGER
+ * </pre>
+ * @return a basic ASN.1 object representation.
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ return content;
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/cmp/PollRepContent.java b/core/src/main/java/org/spongycastle/asn1/cmp/PollRepContent.java
new file mode 100644
index 00000000..d2116b9a
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/cmp/PollRepContent.java
@@ -0,0 +1,119 @@
+package org.spongycastle.asn1.cmp;
+
+import org.spongycastle.asn1.ASN1EncodableVector;
+import org.spongycastle.asn1.ASN1Integer;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.DERSequence;
+
+public class PollRepContent
+ extends ASN1Object
+{
+ private ASN1Integer[] certReqId;
+ private ASN1Integer[] checkAfter;
+ private PKIFreeText[] reason;
+
+ private PollRepContent(ASN1Sequence seq)
+ {
+ certReqId = new ASN1Integer[seq.size()];
+ checkAfter = new ASN1Integer[seq.size()];
+ reason = new PKIFreeText[seq.size()];
+
+ for (int i = 0; i != seq.size(); i++)
+ {
+ ASN1Sequence s = ASN1Sequence.getInstance(seq.getObjectAt(i));
+
+ certReqId[i] = ASN1Integer.getInstance(s.getObjectAt(0));
+ checkAfter[i] = ASN1Integer.getInstance(s.getObjectAt(1));
+
+ if (s.size() > 2)
+ {
+ reason[i] = PKIFreeText.getInstance(s.getObjectAt(2));
+ }
+ }
+ }
+
+ public static PollRepContent getInstance(Object o)
+ {
+ if (o instanceof PollRepContent)
+ {
+ return (PollRepContent)o;
+ }
+
+ if (o != null)
+ {
+ return new PollRepContent(ASN1Sequence.getInstance(o));
+ }
+
+ return null;
+ }
+
+ public PollRepContent(ASN1Integer certReqId, ASN1Integer checkAfter)
+ {
+ this(certReqId, checkAfter, null);
+ }
+
+ public PollRepContent(ASN1Integer certReqId, ASN1Integer checkAfter, PKIFreeText reason)
+ {
+ this.certReqId = new ASN1Integer[1];
+ this.checkAfter = new ASN1Integer[1];
+ this.reason = new PKIFreeText[1];
+
+ this.certReqId[0] = certReqId;
+ this.checkAfter[0] = checkAfter;
+ this.reason[0] = reason;
+ }
+
+ public int size()
+ {
+ return certReqId.length;
+ }
+
+ public ASN1Integer getCertReqId(int index)
+ {
+ return certReqId[index];
+ }
+
+ public ASN1Integer getCheckAfter(int index)
+ {
+ return checkAfter[index];
+ }
+
+ public PKIFreeText getReason(int index)
+ {
+ return reason[index];
+ }
+
+ /**
+ * <pre>
+ * PollRepContent ::= SEQUENCE OF SEQUENCE {
+ * certReqId INTEGER,
+ * checkAfter INTEGER, -- time in seconds
+ * reason PKIFreeText OPTIONAL
+ * }
+ * </pre>
+ * @return a basic ASN.1 object representation.
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector outer = new ASN1EncodableVector();
+
+ for (int i = 0; i != certReqId.length; i++)
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(certReqId[i]);
+ v.add(checkAfter[i]);
+
+ if (reason[i] != null)
+ {
+ v.add(reason[i]);
+ }
+
+ outer.add(new DERSequence(v));
+ }
+
+ return new DERSequence(outer);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/cmp/PollReqContent.java b/core/src/main/java/org/spongycastle/asn1/cmp/PollReqContent.java
new file mode 100644
index 00000000..58bfbd08
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/cmp/PollReqContent.java
@@ -0,0 +1,80 @@
+package org.spongycastle.asn1.cmp;
+
+import org.spongycastle.asn1.ASN1Integer;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.DERSequence;
+
+public class PollReqContent
+ extends ASN1Object
+{
+ private ASN1Sequence content;
+
+ private PollReqContent(ASN1Sequence seq)
+ {
+ content = seq;
+ }
+
+ public static PollReqContent getInstance(Object o)
+ {
+ if (o instanceof PollReqContent)
+ {
+ return (PollReqContent)o;
+ }
+
+ if (o != null)
+ {
+ return new PollReqContent(ASN1Sequence.getInstance(o));
+ }
+
+ return null;
+ }
+
+ /**
+ * Create a pollReqContent for a single certReqId.
+ *
+ * @param certReqId the certificate request ID.
+ */
+ public PollReqContent(ASN1Integer certReqId)
+ {
+ this(new DERSequence(new DERSequence(certReqId)));
+ }
+
+ public ASN1Integer[][] getCertReqIds()
+ {
+ ASN1Integer[][] result = new ASN1Integer[content.size()][];
+
+ for (int i = 0; i != result.length; i++)
+ {
+ result[i] = sequenceToASN1IntegerArray((ASN1Sequence)content.getObjectAt(i));
+ }
+
+ return result;
+ }
+
+ private static ASN1Integer[] sequenceToASN1IntegerArray(ASN1Sequence seq)
+ {
+ ASN1Integer[] result = new ASN1Integer[seq.size()];
+
+ for (int i = 0; i != result.length; i++)
+ {
+ result[i] = ASN1Integer.getInstance(seq.getObjectAt(i));
+ }
+
+ return result;
+ }
+
+ /**
+ * <pre>
+ * PollReqContent ::= SEQUENCE OF SEQUENCE {
+ * certReqId INTEGER
+ * }
+ * </pre>
+ * @return a basic ASN.1 object representation.
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ return content;
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/cmp/ProtectedPart.java b/core/src/main/java/org/spongycastle/asn1/cmp/ProtectedPart.java
new file mode 100644
index 00000000..7594e8ec
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/cmp/ProtectedPart.java
@@ -0,0 +1,70 @@
+package org.spongycastle.asn1.cmp;
+
+import org.spongycastle.asn1.ASN1EncodableVector;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.DERSequence;
+
+public class ProtectedPart
+ extends ASN1Object
+{
+ private PKIHeader header;
+ private PKIBody body;
+
+ private ProtectedPart(ASN1Sequence seq)
+ {
+ header = PKIHeader.getInstance(seq.getObjectAt(0));
+ body = PKIBody.getInstance(seq.getObjectAt(1));
+ }
+
+ public static ProtectedPart getInstance(Object o)
+ {
+ if (o instanceof ProtectedPart)
+ {
+ return (ProtectedPart)o;
+ }
+
+ if (o != null)
+ {
+ return new ProtectedPart(ASN1Sequence.getInstance(o));
+ }
+
+ return null;
+ }
+
+ public ProtectedPart(PKIHeader header, PKIBody body)
+ {
+ this.header = header;
+ this.body = body;
+ }
+
+ public PKIHeader getHeader()
+ {
+ return header;
+ }
+
+ public PKIBody getBody()
+ {
+ return body;
+ }
+
+ /**
+ * <pre>
+ * ProtectedPart ::= SEQUENCE {
+ * header PKIHeader,
+ * body PKIBody
+ * }
+ * </pre>
+ * @return a basic ASN.1 object representation.
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(header);
+ v.add(body);
+
+ return new DERSequence(v);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/cmp/RevAnnContent.java b/core/src/main/java/org/spongycastle/asn1/cmp/RevAnnContent.java
new file mode 100644
index 00000000..39d4de9e
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/cmp/RevAnnContent.java
@@ -0,0 +1,103 @@
+package org.spongycastle.asn1.cmp;
+
+import org.spongycastle.asn1.ASN1EncodableVector;
+import org.spongycastle.asn1.ASN1GeneralizedTime;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.DERSequence;
+import org.spongycastle.asn1.crmf.CertId;
+import org.spongycastle.asn1.x509.Extensions;
+
+public class RevAnnContent
+ extends ASN1Object
+{
+ private PKIStatus status;
+ private CertId certId;
+ private ASN1GeneralizedTime willBeRevokedAt;
+ private ASN1GeneralizedTime badSinceDate;
+ private Extensions crlDetails;
+
+ private RevAnnContent(ASN1Sequence seq)
+ {
+ status = PKIStatus.getInstance(seq.getObjectAt(0));
+ certId = CertId.getInstance(seq.getObjectAt(1));
+ willBeRevokedAt = ASN1GeneralizedTime.getInstance(seq.getObjectAt(2));
+ badSinceDate = ASN1GeneralizedTime.getInstance(seq.getObjectAt(3));
+
+ if (seq.size() > 4)
+ {
+ crlDetails = Extensions.getInstance(seq.getObjectAt(4));
+ }
+ }
+
+ public static RevAnnContent getInstance(Object o)
+ {
+ if (o instanceof RevAnnContent)
+ {
+ return (RevAnnContent)o;
+ }
+
+ if (o != null)
+ {
+ return new RevAnnContent(ASN1Sequence.getInstance(o));
+ }
+
+ return null;
+ }
+
+ public PKIStatus getStatus()
+ {
+ return status;
+ }
+
+ public CertId getCertId()
+ {
+ return certId;
+ }
+
+ public ASN1GeneralizedTime getWillBeRevokedAt()
+ {
+ return willBeRevokedAt;
+ }
+
+ public ASN1GeneralizedTime getBadSinceDate()
+ {
+ return badSinceDate;
+ }
+
+ public Extensions getCrlDetails()
+ {
+ 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 ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(status);
+ v.add(certId);
+ v.add(willBeRevokedAt);
+ v.add(badSinceDate);
+
+ if (crlDetails != null)
+ {
+ v.add(crlDetails);
+ }
+
+ return new DERSequence(v);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/cmp/RevDetails.java b/core/src/main/java/org/spongycastle/asn1/cmp/RevDetails.java
new file mode 100644
index 00000000..6009a3be
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/cmp/RevDetails.java
@@ -0,0 +1,100 @@
+package org.spongycastle.asn1.cmp;
+
+import org.spongycastle.asn1.ASN1EncodableVector;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.DERSequence;
+import org.spongycastle.asn1.crmf.CertTemplate;
+import org.spongycastle.asn1.x509.Extensions;
+import org.spongycastle.asn1.x509.X509Extensions;
+
+public class RevDetails
+ extends ASN1Object
+{
+ private CertTemplate certDetails;
+ private Extensions crlEntryDetails;
+
+ private RevDetails(ASN1Sequence seq)
+ {
+ certDetails = CertTemplate.getInstance(seq.getObjectAt(0));
+ if (seq.size() > 1)
+ {
+ crlEntryDetails = Extensions.getInstance(seq.getObjectAt(1));
+ }
+ }
+
+ public static RevDetails getInstance(Object o)
+ {
+ if (o instanceof RevDetails)
+ {
+ return (RevDetails)o;
+ }
+
+ if (o != null)
+ {
+ return new RevDetails(ASN1Sequence.getInstance(o));
+ }
+
+ return null;
+ }
+
+ public RevDetails(CertTemplate certDetails)
+ {
+ this.certDetails = certDetails;
+ }
+
+ /**
+ * @deprecated use method taking Extensions
+ * @param certDetails
+ * @param crlEntryDetails
+ */
+ public RevDetails(CertTemplate certDetails, X509Extensions crlEntryDetails)
+ {
+ this.certDetails = certDetails;
+ this.crlEntryDetails = Extensions.getInstance(crlEntryDetails.toASN1Primitive());
+ }
+
+ public RevDetails(CertTemplate certDetails, Extensions crlEntryDetails)
+ {
+ this.certDetails = certDetails;
+ this.crlEntryDetails = crlEntryDetails;
+ }
+
+ public CertTemplate getCertDetails()
+ {
+ return certDetails;
+ }
+
+ public Extensions getCrlEntryDetails()
+ {
+ 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 ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(certDetails);
+
+ if (crlEntryDetails != null)
+ {
+ v.add(crlEntryDetails);
+ }
+
+ return new DERSequence(v);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/cmp/RevRepContent.java b/core/src/main/java/org/spongycastle/asn1/cmp/RevRepContent.java
new file mode 100644
index 00000000..b6774193
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/cmp/RevRepContent.java
@@ -0,0 +1,137 @@
+package org.spongycastle.asn1.cmp;
+
+import java.util.Enumeration;
+
+import org.spongycastle.asn1.ASN1Encodable;
+import org.spongycastle.asn1.ASN1EncodableVector;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.ASN1TaggedObject;
+import org.spongycastle.asn1.DERSequence;
+import org.spongycastle.asn1.DERTaggedObject;
+import org.spongycastle.asn1.crmf.CertId;
+import org.spongycastle.asn1.x509.CertificateList;
+
+public class RevRepContent
+ extends ASN1Object
+{
+ private ASN1Sequence status;
+ private ASN1Sequence revCerts;
+ private ASN1Sequence crls;
+
+ private RevRepContent(ASN1Sequence seq)
+ {
+ Enumeration en = seq.getObjects();
+
+ status = ASN1Sequence.getInstance(en.nextElement());
+ while (en.hasMoreElements())
+ {
+ ASN1TaggedObject tObj = ASN1TaggedObject.getInstance(en.nextElement());
+
+ if (tObj.getTagNo() == 0)
+ {
+ revCerts = ASN1Sequence.getInstance(tObj, true);
+ }
+ else
+ {
+ crls = ASN1Sequence.getInstance(tObj, true);
+ }
+ }
+ }
+
+ public static RevRepContent getInstance(Object o)
+ {
+ if (o instanceof RevRepContent)
+ {
+ return (RevRepContent)o;
+ }
+
+ if (o != null)
+ {
+ return new RevRepContent(ASN1Sequence.getInstance(o));
+ }
+
+ return null;
+ }
+
+ public PKIStatusInfo[] getStatus()
+ {
+ PKIStatusInfo[] results = new PKIStatusInfo[status.size()];
+
+ for (int i = 0; i != results.length; i++)
+ {
+ results[i] = PKIStatusInfo.getInstance(status.getObjectAt(i));
+ }
+
+ return results;
+ }
+
+ public CertId[] getRevCerts()
+ {
+ if (revCerts == null)
+ {
+ return null;
+ }
+
+ CertId[] results = new CertId[revCerts.size()];
+
+ for (int i = 0; i != results.length; i++)
+ {
+ results[i] = CertId.getInstance(revCerts.getObjectAt(i));
+ }
+
+ return results;
+ }
+
+ public CertificateList[] getCrls()
+ {
+ if (crls == null)
+ {
+ return null;
+ }
+
+ CertificateList[] results = new CertificateList[crls.size()];
+
+ for (int i = 0; i != results.length; i++)
+ {
+ results[i] = CertificateList.getInstance(crls.getObjectAt(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 ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(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/core/src/main/java/org/spongycastle/asn1/cmp/RevRepContentBuilder.java b/core/src/main/java/org/spongycastle/asn1/cmp/RevRepContentBuilder.java
new file mode 100644
index 00000000..d154f17c
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/cmp/RevRepContentBuilder.java
@@ -0,0 +1,59 @@
+package org.spongycastle.asn1.cmp;
+
+import org.spongycastle.asn1.ASN1EncodableVector;
+import org.spongycastle.asn1.DERSequence;
+import org.spongycastle.asn1.DERTaggedObject;
+import org.spongycastle.asn1.crmf.CertId;
+import org.spongycastle.asn1.x509.CertificateList;
+
+public class RevRepContentBuilder
+{
+ private ASN1EncodableVector status = new ASN1EncodableVector();
+ private ASN1EncodableVector revCerts = new ASN1EncodableVector();
+ private ASN1EncodableVector crls = new ASN1EncodableVector();
+
+ public RevRepContentBuilder add(PKIStatusInfo status)
+ {
+ this.status.add(status);
+
+ return this;
+ }
+
+ public RevRepContentBuilder add(PKIStatusInfo status, CertId certId)
+ {
+ if (this.status.size() != this.revCerts.size())
+ {
+ throw new IllegalStateException("status and revCerts sequence must be in common order");
+ }
+ this.status.add(status);
+ this.revCerts.add(certId);
+
+ return this;
+ }
+
+ public RevRepContentBuilder addCrl(CertificateList crl)
+ {
+ this.crls.add(crl);
+
+ return this;
+ }
+
+ public RevRepContent build()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(new DERSequence(status));
+
+ if (revCerts.size() != 0)
+ {
+ v.add(new DERTaggedObject(true, 0, new DERSequence(revCerts)));
+ }
+
+ if (crls.size() != 0)
+ {
+ v.add(new DERTaggedObject(true, 1, new DERSequence(crls)));
+ }
+
+ return RevRepContent.getInstance(new DERSequence(v));
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/cmp/RevReqContent.java b/core/src/main/java/org/spongycastle/asn1/cmp/RevReqContent.java
new file mode 100644
index 00000000..e232417b
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/cmp/RevReqContent.java
@@ -0,0 +1,73 @@
+package org.spongycastle.asn1.cmp;
+
+import org.spongycastle.asn1.ASN1EncodableVector;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.DERSequence;
+
+public class RevReqContent
+ extends ASN1Object
+{
+ private ASN1Sequence content;
+
+ private RevReqContent(ASN1Sequence seq)
+ {
+ content = seq;
+ }
+
+ public static RevReqContent getInstance(Object o)
+ {
+ if (o instanceof RevReqContent)
+ {
+ return (RevReqContent)o;
+ }
+
+ if (o != null)
+ {
+ return new RevReqContent(ASN1Sequence.getInstance(o));
+ }
+
+ return null;
+ }
+
+ public RevReqContent(RevDetails revDetails)
+ {
+ this.content = new DERSequence(revDetails);
+ }
+
+ public RevReqContent(RevDetails[] revDetailsArray)
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ for (int i = 0; i != revDetailsArray.length; i++)
+ {
+ v.add(revDetailsArray[i]);
+ }
+
+ this.content = new DERSequence(v);
+ }
+
+ public RevDetails[] toRevDetailsArray()
+ {
+ RevDetails[] result = new RevDetails[content.size()];
+
+ for (int i = 0; i != result.length; i++)
+ {
+ result[i] = RevDetails.getInstance(content.getObjectAt(i));
+ }
+
+ return result;
+ }
+
+ /**
+ * <pre>
+ * RevReqContent ::= SEQUENCE OF RevDetails
+ * </pre>
+ * @return a basic ASN.1 object representation.
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ return content;
+ }
+}