diff options
author | Sergio Giro <sgiro@google.com> | 2016-02-01 14:37:23 +0000 |
---|---|---|
committer | Sergio Giro <sgiro@google.com> | 2016-02-01 15:16:12 +0000 |
commit | 397d32894b89b506dc318e0f83446187c9b76ebe (patch) | |
tree | 8229ff72c8cbb06f49dce3a8382930919fa6fc2b /bcprov/src/main/java/org/bouncycastle/asn1/cms | |
parent | 9b30eb05e5be69d51881a0d1b31e503e97acd784 (diff) | |
parent | 6d876f3f0ae553704a1dcf7e89003fcf14717037 (diff) | |
download | android_external_bouncycastle-397d32894b89b506dc318e0f83446187c9b76ebe.tar.gz android_external_bouncycastle-397d32894b89b506dc318e0f83446187c9b76ebe.tar.bz2 android_external_bouncycastle-397d32894b89b506dc318e0f83446187c9b76ebe.zip |
Merge remote-tracking branch 'aosp/upstream-master' into merge-152-from-upstream
As to set a common ancestor for future merges from aosp/upstream-master
(when updating to new versions of bouncycastle).
We'll override all the changes of this commit with patch
https://android-review.googlesource.com/#/c/199872
Change-Id: I53a7f797b520a6e119878dbae53246cdcc585ddf
Diffstat (limited to 'bcprov/src/main/java/org/bouncycastle/asn1/cms')
42 files changed, 5233 insertions, 3 deletions
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/cms/AuthEnvelopedData.java b/bcprov/src/main/java/org/bouncycastle/asn1/cms/AuthEnvelopedData.java new file mode 100644 index 0000000..034753f --- /dev/null +++ b/bcprov/src/main/java/org/bouncycastle/asn1/cms/AuthEnvelopedData.java @@ -0,0 +1,248 @@ +package org.bouncycastle.asn1.cms; + +import org.bouncycastle.asn1.ASN1EncodableVector; +import org.bouncycastle.asn1.ASN1Integer; +import org.bouncycastle.asn1.ASN1Object; +import org.bouncycastle.asn1.ASN1OctetString; +import org.bouncycastle.asn1.ASN1Primitive; +import org.bouncycastle.asn1.ASN1Sequence; +import org.bouncycastle.asn1.ASN1Set; +import org.bouncycastle.asn1.ASN1TaggedObject; +import org.bouncycastle.asn1.BERSequence; +import org.bouncycastle.asn1.DERTaggedObject; + +/** + * <a href="http://tools.ietf.org/html/rfc5083">RFC 5083</a>: + * + * CMS AuthEnveloped Data object. + * <p> + * ASN.1: + * <pre> + * id-ct-authEnvelopedData OBJECT IDENTIFIER ::= { iso(1) + * member-body(2) us(840) rsadsi(113549) pkcs(1) pkcs-9(9) + * smime(16) ct(1) 23 } + * + * AuthEnvelopedData ::= SEQUENCE { + * version CMSVersion, + * originatorInfo [0] IMPLICIT OriginatorInfo OPTIONAL, + * recipientInfos RecipientInfos, + * authEncryptedContentInfo EncryptedContentInfo, + * authAttrs [1] IMPLICIT AuthAttributes OPTIONAL, + * mac MessageAuthenticationCode, + * unauthAttrs [2] IMPLICIT UnauthAttributes OPTIONAL } + * </pre> + */ +public class AuthEnvelopedData + extends ASN1Object +{ + private ASN1Integer version; + private OriginatorInfo originatorInfo; + private ASN1Set recipientInfos; + private EncryptedContentInfo authEncryptedContentInfo; + private ASN1Set authAttrs; + private ASN1OctetString mac; + private ASN1Set unauthAttrs; + + public AuthEnvelopedData( + OriginatorInfo originatorInfo, + ASN1Set recipientInfos, + EncryptedContentInfo authEncryptedContentInfo, + ASN1Set authAttrs, + ASN1OctetString mac, + ASN1Set unauthAttrs) + { + // "It MUST be set to 0." + this.version = new ASN1Integer(0); + + this.originatorInfo = originatorInfo; + + // TODO + // "There MUST be at least one element in the collection." + this.recipientInfos = recipientInfos; + + this.authEncryptedContentInfo = authEncryptedContentInfo; + + // TODO + // "The authAttrs MUST be present if the content type carried in + // EncryptedContentInfo is not id-data." + this.authAttrs = authAttrs; + + this.mac = mac; + + this.unauthAttrs = unauthAttrs; + } + + /** + * Constructs AuthEnvelopedData by parsing supplied ASN1Sequence + * <p> + * @param seq An ASN1Sequence with AuthEnvelopedData + * @deprecated use getInstance(). + */ + public AuthEnvelopedData( + ASN1Sequence seq) + { + int index = 0; + + // TODO + // "It MUST be set to 0." + ASN1Primitive tmp = seq.getObjectAt(index++).toASN1Primitive(); + version = (ASN1Integer)tmp; + + tmp = seq.getObjectAt(index++).toASN1Primitive(); + if (tmp instanceof ASN1TaggedObject) + { + originatorInfo = OriginatorInfo.getInstance((ASN1TaggedObject)tmp, false); + tmp = seq.getObjectAt(index++).toASN1Primitive(); + } + + // TODO + // "There MUST be at least one element in the collection." + recipientInfos = ASN1Set.getInstance(tmp); + + tmp = seq.getObjectAt(index++).toASN1Primitive(); + authEncryptedContentInfo = EncryptedContentInfo.getInstance(tmp); + + tmp = seq.getObjectAt(index++).toASN1Primitive(); + if (tmp instanceof ASN1TaggedObject) + { + authAttrs = ASN1Set.getInstance((ASN1TaggedObject)tmp, false); + tmp = seq.getObjectAt(index++).toASN1Primitive(); + } + else + { + // TODO + // "The authAttrs MUST be present if the content type carried in + // EncryptedContentInfo is not id-data." + } + + mac = ASN1OctetString.getInstance(tmp); + + if (seq.size() > index) + { + tmp = seq.getObjectAt(index++).toASN1Primitive(); + unauthAttrs = ASN1Set.getInstance((ASN1TaggedObject)tmp, false); + } + } + + /** + * Return an AuthEnvelopedData object from a tagged object. + * <p> + * Accepted inputs: + * <ul> + * <li> {@link org.bouncycastle.asn1.ASN1Sequence#getInstance(java.lang.Object) ASN1Sequence} input formats + * </ul> + * + + * @param obj the tagged object holding the object we want. + * @param explicit true if the object is meant to be explicitly + * tagged false otherwise. + * @throws IllegalArgumentException if the object held by the + * tagged object cannot be converted. + */ + public static AuthEnvelopedData getInstance( + ASN1TaggedObject obj, + boolean explicit) + { + return getInstance(ASN1Sequence.getInstance(obj, explicit)); + } + + /** + * Return an AuthEnvelopedData object from the given object. + * <p> + * Accepted inputs: + * <ul> + * <li> null → null + * <li> {@link AuthEnvelopedData} object + * <li> {@link ASN1Sequence org.bouncycastle.asn1.ASN1Sequence} input formats with AuthEnvelopedData structure inside + * </ul> + * + * @param obj The object we want converted. + * @throws IllegalArgumentException if the object cannot be converted, or was null. + */ + public static AuthEnvelopedData getInstance( + Object obj) + { + if (obj == null || obj instanceof AuthEnvelopedData) + { + return (AuthEnvelopedData)obj; + } + + if (obj instanceof ASN1Sequence) + { + return new AuthEnvelopedData((ASN1Sequence)obj); + } + + throw new IllegalArgumentException("Invalid AuthEnvelopedData: " + obj.getClass().getName()); + } + + public ASN1Integer getVersion() + { + return version; + } + + public OriginatorInfo getOriginatorInfo() + { + return originatorInfo; + } + + public ASN1Set getRecipientInfos() + { + return recipientInfos; + } + + public EncryptedContentInfo getAuthEncryptedContentInfo() + { + return authEncryptedContentInfo; + } + + public ASN1Set getAuthAttrs() + { + return authAttrs; + } + + public ASN1OctetString getMac() + { + return mac; + } + + public ASN1Set getUnauthAttrs() + { + return unauthAttrs; + } + + /** + * Produce an object suitable for an ASN1OutputStream. + */ + public ASN1Primitive toASN1Primitive() + { + ASN1EncodableVector v = new ASN1EncodableVector(); + + v.add(version); + + if (originatorInfo != null) + { + v.add(new DERTaggedObject(false, 0, originatorInfo)); + } + + v.add(recipientInfos); + v.add(authEncryptedContentInfo); + + // "authAttrs optionally contains the authenticated attributes." + if (authAttrs != null) + { + // "AuthAttributes MUST be DER encoded, even if the rest of the + // AuthEnvelopedData structure is BER encoded." + v.add(new DERTaggedObject(false, 1, authAttrs)); + } + + v.add(mac); + + // "unauthAttrs optionally contains the unauthenticated attributes." + if (unauthAttrs != null) + { + v.add(new DERTaggedObject(false, 2, unauthAttrs)); + } + + return new BERSequence(v); + } +} diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/cms/AuthEnvelopedDataParser.java b/bcprov/src/main/java/org/bouncycastle/asn1/cms/AuthEnvelopedDataParser.java new file mode 100644 index 0000000..8460c33 --- /dev/null +++ b/bcprov/src/main/java/org/bouncycastle/asn1/cms/AuthEnvelopedDataParser.java @@ -0,0 +1,157 @@ +package org.bouncycastle.asn1.cms; + +import java.io.IOException; + +import org.bouncycastle.asn1.ASN1Encodable; +import org.bouncycastle.asn1.ASN1Integer; +import org.bouncycastle.asn1.ASN1OctetString; +import org.bouncycastle.asn1.ASN1SequenceParser; +import org.bouncycastle.asn1.ASN1SetParser; +import org.bouncycastle.asn1.ASN1TaggedObjectParser; +import org.bouncycastle.asn1.BERTags; + +/** + * Parse {@link AuthEnvelopedData} input stream. + * + * <pre> + * AuthEnvelopedData ::= SEQUENCE { + * version CMSVersion, + * originatorInfo [0] IMPLICIT OriginatorInfo OPTIONAL, + * recipientInfos RecipientInfos, + * authEncryptedContentInfo EncryptedContentInfo, + * authAttrs [1] IMPLICIT AuthAttributes OPTIONAL, + * mac MessageAuthenticationCode, + * unauthAttrs [2] IMPLICIT UnauthAttributes OPTIONAL } + * </pre> + */ +public class AuthEnvelopedDataParser +{ + private ASN1SequenceParser seq; + private ASN1Integer version; + private ASN1Encodable nextObject; + private boolean originatorInfoCalled; + + public AuthEnvelopedDataParser(ASN1SequenceParser seq) throws IOException + { + this.seq = seq; + + // TODO + // "It MUST be set to 0." + this.version = ASN1Integer.getInstance(seq.readObject()); + } + + public ASN1Integer getVersion() + { + return version; + } + + public OriginatorInfo getOriginatorInfo() + throws IOException + { + originatorInfoCalled = true; + + if (nextObject == null) + { + nextObject = seq.readObject(); + } + + if (nextObject instanceof ASN1TaggedObjectParser && ((ASN1TaggedObjectParser)nextObject).getTagNo() == 0) + { + ASN1SequenceParser originatorInfo = (ASN1SequenceParser) ((ASN1TaggedObjectParser)nextObject).getObjectParser(BERTags.SEQUENCE, false); + nextObject = null; + return OriginatorInfo.getInstance(originatorInfo.toASN1Primitive()); + } + + return null; + } + + public ASN1SetParser getRecipientInfos() + throws IOException + { + if (!originatorInfoCalled) + { + getOriginatorInfo(); + } + + if (nextObject == null) + { + nextObject = seq.readObject(); + } + + ASN1SetParser recipientInfos = (ASN1SetParser)nextObject; + nextObject = null; + return recipientInfos; + } + + public EncryptedContentInfoParser getAuthEncryptedContentInfo() + throws IOException + { + if (nextObject == null) + { + nextObject = seq.readObject(); + } + + if (nextObject != null) + { + ASN1SequenceParser o = (ASN1SequenceParser) nextObject; + nextObject = null; + return new EncryptedContentInfoParser(o); + } + + return null; + } + + public ASN1SetParser getAuthAttrs() + throws IOException + { + if (nextObject == null) + { + nextObject = seq.readObject(); + } + + if (nextObject instanceof ASN1TaggedObjectParser) + { + ASN1Encodable o = nextObject; + nextObject = null; + return (ASN1SetParser)((ASN1TaggedObjectParser)o).getObjectParser(BERTags.SET, false); + } + + // TODO + // "The authAttrs MUST be present if the content type carried in + // EncryptedContentInfo is not id-data." + + return null; + } + + public ASN1OctetString getMac() + throws IOException + { + if (nextObject == null) + { + nextObject = seq.readObject(); + } + + ASN1Encodable o = nextObject; + nextObject = null; + + return ASN1OctetString.getInstance(o.toASN1Primitive()); + } + + public ASN1SetParser getUnauthAttrs() + throws IOException + { + if (nextObject == null) + { + nextObject = seq.readObject(); + } + + if (nextObject != null) + { + ASN1Encodable o = nextObject; + nextObject = null; + return (ASN1SetParser)((ASN1TaggedObjectParser)o).getObjectParser(BERTags.SET, false); + } + + return null; + } +} diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/cms/AuthenticatedData.java b/bcprov/src/main/java/org/bouncycastle/asn1/cms/AuthenticatedData.java new file mode 100644 index 0000000..c0945f3 --- /dev/null +++ b/bcprov/src/main/java/org/bouncycastle/asn1/cms/AuthenticatedData.java @@ -0,0 +1,312 @@ +package org.bouncycastle.asn1.cms; + +import java.util.Enumeration; + +import org.bouncycastle.asn1.ASN1EncodableVector; +import org.bouncycastle.asn1.ASN1Integer; +import org.bouncycastle.asn1.ASN1Object; +import org.bouncycastle.asn1.ASN1OctetString; +import org.bouncycastle.asn1.ASN1Primitive; +import org.bouncycastle.asn1.ASN1Sequence; +import org.bouncycastle.asn1.ASN1Set; +import org.bouncycastle.asn1.ASN1TaggedObject; +import org.bouncycastle.asn1.BERSequence; +import org.bouncycastle.asn1.DERTaggedObject; +import org.bouncycastle.asn1.x509.AlgorithmIdentifier; + +/** + * <a href="http://tools.ietf.org/html/rfc5652#section-9.1">RFC 5652</a> section 9.1: + * The AuthenticatedData carries AuthAttributes and other data + * which define what really is being signed. + * <p> + * <pre> + * AuthenticatedData ::= SEQUENCE { + * version CMSVersion, + * originatorInfo [0] IMPLICIT OriginatorInfo OPTIONAL, + * recipientInfos RecipientInfos, + * macAlgorithm MessageAuthenticationCodeAlgorithm, + * digestAlgorithm [1] DigestAlgorithmIdentifier OPTIONAL, + * encapContentInfo EncapsulatedContentInfo, + * authAttrs [2] IMPLICIT AuthAttributes OPTIONAL, + * mac MessageAuthenticationCode, + * unauthAttrs [3] IMPLICIT UnauthAttributes OPTIONAL } + * + * AuthAttributes ::= SET SIZE (1..MAX) OF Attribute + * + * UnauthAttributes ::= SET SIZE (1..MAX) OF Attribute + * + * MessageAuthenticationCode ::= OCTET STRING + * </pre> + */ +public class AuthenticatedData + extends ASN1Object +{ + private ASN1Integer version; + private OriginatorInfo originatorInfo; + private ASN1Set recipientInfos; + private AlgorithmIdentifier macAlgorithm; + private AlgorithmIdentifier digestAlgorithm; + private ContentInfo encapsulatedContentInfo; + private ASN1Set authAttrs; + private ASN1OctetString mac; + private ASN1Set unauthAttrs; + + public AuthenticatedData( + OriginatorInfo originatorInfo, + ASN1Set recipientInfos, + AlgorithmIdentifier macAlgorithm, + AlgorithmIdentifier digestAlgorithm, + ContentInfo encapsulatedContent, + ASN1Set authAttrs, + ASN1OctetString mac, + ASN1Set unauthAttrs) + { + if (digestAlgorithm != null || authAttrs != null) + { + if (digestAlgorithm == null || authAttrs == null) + { + throw new IllegalArgumentException("digestAlgorithm and authAttrs must be set together"); + } + } + + version = new ASN1Integer(calculateVersion(originatorInfo)); + + this.originatorInfo = originatorInfo; + this.macAlgorithm = macAlgorithm; + this.digestAlgorithm = digestAlgorithm; + this.recipientInfos = recipientInfos; + this.encapsulatedContentInfo = encapsulatedContent; + this.authAttrs = authAttrs; + this.mac = mac; + this.unauthAttrs = unauthAttrs; + } + + /** + * @deprecated use getInstance() + */ + public AuthenticatedData( + ASN1Sequence seq) + { + int index = 0; + + version = (ASN1Integer)seq.getObjectAt(index++); + + Object tmp = seq.getObjectAt(index++); + + if (tmp instanceof ASN1TaggedObject) + { + originatorInfo = OriginatorInfo.getInstance((ASN1TaggedObject)tmp, false); + tmp = seq.getObjectAt(index++); + } + + recipientInfos = ASN1Set.getInstance(tmp); + macAlgorithm = AlgorithmIdentifier.getInstance(seq.getObjectAt(index++)); + + tmp = seq.getObjectAt(index++); + + if (tmp instanceof ASN1TaggedObject) + { + digestAlgorithm = AlgorithmIdentifier.getInstance((ASN1TaggedObject)tmp, false); + tmp = seq.getObjectAt(index++); + } + + encapsulatedContentInfo = ContentInfo.getInstance(tmp); + + tmp = seq.getObjectAt(index++); + + if (tmp instanceof ASN1TaggedObject) + { + authAttrs = ASN1Set.getInstance((ASN1TaggedObject)tmp, false); + tmp = seq.getObjectAt(index++); + } + + mac = ASN1OctetString.getInstance(tmp); + + if (seq.size() > index) + { + unauthAttrs = ASN1Set.getInstance((ASN1TaggedObject)seq.getObjectAt(index), false); + } + } + + /** + * Return an AuthenticatedData object from a tagged object. + * + * @param obj the tagged object holding the object we want. + * @param explicit true if the object is meant to be explicitly + * tagged false otherwise. + * @throws IllegalArgumentException if the object held by the + * tagged object cannot be converted. + */ + public static AuthenticatedData getInstance( + ASN1TaggedObject obj, + boolean explicit) + { + return getInstance(ASN1Sequence.getInstance(obj, explicit)); + } + + /** + * Return an AuthenticatedData object from the given object. + * <p> + * Accepted inputs: + * <ul> + * <li> null → null + * <li> {@link AuthenticatedData} object + * <li> {@link org.bouncycastle.asn1.ASN1Sequence#getInstance(java.lang.Object) ASN1Sequence} input formats with AuthenticatedData structure inside + * </ul> + * + * @param obj the object we want converted. + * @throws IllegalArgumentException if the object cannot be converted. + */ + public static AuthenticatedData getInstance( + Object obj) + { + if (obj == null || obj instanceof AuthenticatedData) + { + return (AuthenticatedData)obj; + } + + if (obj instanceof ASN1Sequence) + { + return new AuthenticatedData((ASN1Sequence)obj); + } + + throw new IllegalArgumentException("Invalid AuthenticatedData: " + obj.getClass().getName()); + } + + public ASN1Integer getVersion() + { + return version; + } + + public OriginatorInfo getOriginatorInfo() + { + return originatorInfo; + } + + public ASN1Set getRecipientInfos() + { + return recipientInfos; + } + + public AlgorithmIdentifier getMacAlgorithm() + { + return macAlgorithm; + } + + public AlgorithmIdentifier getDigestAlgorithm() + { + return digestAlgorithm; + } + + public ContentInfo getEncapsulatedContentInfo() + { + return encapsulatedContentInfo; + } + + public ASN1Set getAuthAttrs() + { + return authAttrs; + } + + public ASN1OctetString getMac() + { + return mac; + } + + public ASN1Set getUnauthAttrs() + { + return unauthAttrs; + } + + /** + * Produce an object suitable for an ASN1OutputStream. + */ + public ASN1Primitive toASN1Primitive() + { + ASN1EncodableVector v = new ASN1EncodableVector(); + + v.add(version); + + if (originatorInfo != null) + { + v.add(new DERTaggedObject(false, 0, originatorInfo)); + } + + v.add(recipientInfos); + v.add(macAlgorithm); + + if (digestAlgorithm != null) + { + v.add(new DERTaggedObject(false, 1, digestAlgorithm)); + } + + v.add(encapsulatedContentInfo); + + if (authAttrs != null) + { + v.add(new DERTaggedObject(false, 2, authAttrs)); + } + + v.add(mac); + + if (unauthAttrs != null) + { + v.add(new DERTaggedObject(false, 3, unauthAttrs)); + } + + return new BERSequence(v); + } + + public static int calculateVersion(OriginatorInfo origInfo) + { + if (origInfo == null) + { + return 0; + } + else + { + int ver = 0; + + for (Enumeration e = origInfo.getCertificates().getObjects(); e.hasMoreElements();) + { + Object obj = e.nextElement(); + + if (obj instanceof ASN1TaggedObject) + { + ASN1TaggedObject tag = (ASN1TaggedObject)obj; + + if (tag.getTagNo() == 2) + { + ver = 1; + } + else if (tag.getTagNo() == 3) + { + ver = 3; + break; + } + } + } + + if (origInfo.getCRLs() != null) + { + for (Enumeration e = origInfo.getCRLs().getObjects(); e.hasMoreElements();) + { + Object obj = e.nextElement(); + + if (obj instanceof ASN1TaggedObject) + { + ASN1TaggedObject tag = (ASN1TaggedObject)obj; + + if (tag.getTagNo() == 1) + { + ver = 3; + break; + } + } + } + } + + return ver; + } + } +} diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/cms/AuthenticatedDataParser.java b/bcprov/src/main/java/org/bouncycastle/asn1/cms/AuthenticatedDataParser.java new file mode 100644 index 0000000..ce9aa4f --- /dev/null +++ b/bcprov/src/main/java/org/bouncycastle/asn1/cms/AuthenticatedDataParser.java @@ -0,0 +1,206 @@ +package org.bouncycastle.asn1.cms; + +import java.io.IOException; + +import org.bouncycastle.asn1.ASN1Encodable; +import org.bouncycastle.asn1.ASN1Integer; +import org.bouncycastle.asn1.ASN1OctetString; +import org.bouncycastle.asn1.ASN1SequenceParser; +import org.bouncycastle.asn1.ASN1SetParser; +import org.bouncycastle.asn1.ASN1TaggedObject; +import org.bouncycastle.asn1.ASN1TaggedObjectParser; +import org.bouncycastle.asn1.BERTags; +import org.bouncycastle.asn1.x509.AlgorithmIdentifier; + +/** + * Parse {@link AuthenticatedData} stream. + * <pre> + * AuthenticatedData ::= SEQUENCE { + * version CMSVersion, + * originatorInfo [0] IMPLICIT OriginatorInfo OPTIONAL, + * recipientInfos RecipientInfos, + * macAlgorithm MessageAuthenticationCodeAlgorithm, + * digestAlgorithm [1] DigestAlgorithmIdentifier OPTIONAL, + * encapContentInfo EncapsulatedContentInfo, + * authAttrs [2] IMPLICIT AuthAttributes OPTIONAL, + * mac MessageAuthenticationCode, + * unauthAttrs [3] IMPLICIT UnauthAttributes OPTIONAL } + * + * AuthAttributes ::= SET SIZE (1..MAX) OF Attribute + * + * UnauthAttributes ::= SET SIZE (1..MAX) OF Attribute + * + * MessageAuthenticationCode ::= OCTET STRING + * </pre> + */ +public class AuthenticatedDataParser +{ + private ASN1SequenceParser seq; + private ASN1Integer version; + private ASN1Encodable nextObject; + private boolean originatorInfoCalled; + + public AuthenticatedDataParser( + ASN1SequenceParser seq) + throws IOException + { + this.seq = seq; + this.version = ASN1Integer.getInstance(seq.readObject()); + } + + public ASN1Integer getVersion() + { + return version; + } + + public OriginatorInfo getOriginatorInfo() + throws IOException + { + originatorInfoCalled = true; + + if (nextObject == null) + { + nextObject = seq.readObject(); + } + + if (nextObject instanceof ASN1TaggedObjectParser && ((ASN1TaggedObjectParser)nextObject).getTagNo() == 0) + { + ASN1SequenceParser originatorInfo = (ASN1SequenceParser) ((ASN1TaggedObjectParser)nextObject).getObjectParser(BERTags.SEQUENCE, false); + nextObject = null; + return OriginatorInfo.getInstance(originatorInfo.toASN1Primitive()); + } + + return null; + } + + public ASN1SetParser getRecipientInfos() + throws IOException + { + if (!originatorInfoCalled) + { + getOriginatorInfo(); + } + + if (nextObject == null) + { + nextObject = seq.readObject(); + } + + ASN1SetParser recipientInfos = (ASN1SetParser)nextObject; + nextObject = null; + return recipientInfos; + } + + public AlgorithmIdentifier getMacAlgorithm() + throws IOException + { + if (nextObject == null) + { + nextObject = seq.readObject(); + } + + if (nextObject != null) + { + ASN1SequenceParser o = (ASN1SequenceParser)nextObject; + nextObject = null; + return AlgorithmIdentifier.getInstance(o.toASN1Primitive()); + } + + return null; + } + + public AlgorithmIdentifier getDigestAlgorithm() + throws IOException + { + if (nextObject == null) + { + nextObject = seq.readObject(); + } + + if (nextObject instanceof ASN1TaggedObjectParser) + { + AlgorithmIdentifier obj = AlgorithmIdentifier.getInstance((ASN1TaggedObject)nextObject.toASN1Primitive(), false); + nextObject = null; + return obj; + } + + return null; + } + + /** + * @deprecated use getEncapsulatedContentInfo() + */ + public ContentInfoParser getEnapsulatedContentInfo() + throws IOException + { + return getEncapsulatedContentInfo(); + } + + public ContentInfoParser getEncapsulatedContentInfo() + throws IOException + { + if (nextObject == null) + { + nextObject = seq.readObject(); + } + + if (nextObject != null) + { + ASN1SequenceParser o = (ASN1SequenceParser)nextObject; + nextObject = null; + return new ContentInfoParser(o); + } + + return null; + } + + public ASN1SetParser getAuthAttrs() + throws IOException + { + if (nextObject == null) + { + nextObject = seq.readObject(); + } + + if (nextObject instanceof ASN1TaggedObjectParser) + { + ASN1Encodable o = nextObject; + nextObject = null; + return (ASN1SetParser)((ASN1TaggedObjectParser)o).getObjectParser(BERTags.SET, false); + } + + return null; + } + + public ASN1OctetString getMac() + throws IOException + { + if (nextObject == null) + { + nextObject = seq.readObject(); + } + + ASN1Encodable o = nextObject; + nextObject = null; + + return ASN1OctetString.getInstance(o.toASN1Primitive()); + } + + public ASN1SetParser getUnauthAttrs() + throws IOException + { + if (nextObject == null) + { + nextObject = seq.readObject(); + } + + if (nextObject != null) + { + ASN1Encodable o = nextObject; + nextObject = null; + return (ASN1SetParser)((ASN1TaggedObjectParser)o).getObjectParser(BERTags.SET, false); + } + + return null; + } +} diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/cms/CCMParameters.java b/bcprov/src/main/java/org/bouncycastle/asn1/cms/CCMParameters.java new file mode 100644 index 0000000..3277bb2 --- /dev/null +++ b/bcprov/src/main/java/org/bouncycastle/asn1/cms/CCMParameters.java @@ -0,0 +1,102 @@ +package org.bouncycastle.asn1.cms; + +import org.bouncycastle.asn1.ASN1EncodableVector; +import org.bouncycastle.asn1.ASN1Integer; +import org.bouncycastle.asn1.ASN1Object; +import org.bouncycastle.asn1.ASN1OctetString; +import org.bouncycastle.asn1.ASN1Primitive; +import org.bouncycastle.asn1.ASN1Sequence; +import org.bouncycastle.asn1.DEROctetString; +import org.bouncycastle.asn1.DERSequence; +import org.bouncycastle.util.Arrays; + +/** + * <a href="http://tools.ietf.org/html/rfc5084">RFC 5084</a>: CCMParameters object. + * <p> + * <pre> + CCMParameters ::= SEQUENCE { + aes-nonce OCTET STRING, -- recommended size is 12 octets + aes-ICVlen AES-CCM-ICVlen DEFAULT 12 } + * </pre> + */ +public class CCMParameters + extends ASN1Object +{ + private byte[] nonce; + private int icvLen; + + /** + * Return an CCMParameters object from the given object. + * <p> + * Accepted inputs: + * <ul> + * <li> null → null + * <li> {@link org.bouncycastle.asn1.cms.CCMParameters} object + * <li> {@link org.bouncycastle.asn1.ASN1Sequence#getInstance(Object) ASN1Sequence} input formats with CCMParameters structure inside + * </ul> + * + * @param obj the object we want converted. + * @exception IllegalArgumentException if the object cannot be converted. + */ + public static CCMParameters getInstance( + Object obj) + { + if (obj instanceof CCMParameters) + { + return (CCMParameters)obj; + } + else if (obj != null) + { + return new CCMParameters(ASN1Sequence.getInstance(obj)); + } + + return null; + } + + private CCMParameters( + ASN1Sequence seq) + { + this.nonce = ASN1OctetString.getInstance(seq.getObjectAt(0)).getOctets(); + + if (seq.size() == 2) + { + this.icvLen = ASN1Integer.getInstance(seq.getObjectAt(1)).getValue().intValue(); + } + else + { + this.icvLen = 12; + } + } + + public CCMParameters( + byte[] nonce, + int icvLen) + { + this.nonce = Arrays.clone(nonce); + this.icvLen = icvLen; + } + + public byte[] getNonce() + { + return Arrays.clone(nonce); + } + + public int getIcvLen() + { + return icvLen; + } + + public ASN1Primitive toASN1Primitive() + { + ASN1EncodableVector v = new ASN1EncodableVector(); + + v.add(new DEROctetString(nonce)); + + if (icvLen != 12) + { + v.add(new ASN1Integer(icvLen)); + } + + return new DERSequence(v); + } +} diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/cms/CompressedData.java b/bcprov/src/main/java/org/bouncycastle/asn1/cms/CompressedData.java new file mode 100644 index 0000000..e546470 --- /dev/null +++ b/bcprov/src/main/java/org/bouncycastle/asn1/cms/CompressedData.java @@ -0,0 +1,117 @@ +package org.bouncycastle.asn1.cms; + +import org.bouncycastle.asn1.ASN1EncodableVector; +import org.bouncycastle.asn1.ASN1Integer; +import org.bouncycastle.asn1.ASN1Object; +import org.bouncycastle.asn1.ASN1Primitive; +import org.bouncycastle.asn1.ASN1Sequence; +import org.bouncycastle.asn1.ASN1TaggedObject; +import org.bouncycastle.asn1.BERSequence; +import org.bouncycastle.asn1.x509.AlgorithmIdentifier; + +/** + * <a href="http://tools.ietf.org/html/rfc3274">RFC 3274</a>: CMS Compressed Data. + * + * <pre> + * CompressedData ::= SEQUENCE { + * version CMSVersion, + * compressionAlgorithm CompressionAlgorithmIdentifier, + * encapContentInfo EncapsulatedContentInfo + * } + * </pre> + */ +public class CompressedData + extends ASN1Object +{ + private ASN1Integer version; + private AlgorithmIdentifier compressionAlgorithm; + private ContentInfo encapContentInfo; + + public CompressedData( + AlgorithmIdentifier compressionAlgorithm, + ContentInfo encapContentInfo) + { + this.version = new ASN1Integer(0); + this.compressionAlgorithm = compressionAlgorithm; + this.encapContentInfo = encapContentInfo; + } + + private CompressedData( + ASN1Sequence seq) + { + this.version = (ASN1Integer)seq.getObjectAt(0); + this.compressionAlgorithm = AlgorithmIdentifier.getInstance(seq.getObjectAt(1)); + this.encapContentInfo = ContentInfo.getInstance(seq.getObjectAt(2)); + } + + /** + * Return a CompressedData object from a tagged object. + * + * @param ato the tagged object holding the object we want. + * @param isExplicit true if the object is meant to be explicitly + * tagged false otherwise. + * @exception IllegalArgumentException if the object held by the + * tagged object cannot be converted. + */ + public static CompressedData getInstance( + ASN1TaggedObject ato, + boolean isExplicit) + { + return getInstance(ASN1Sequence.getInstance(ato, isExplicit)); + } + + /** + * Return a CompressedData object from the given object. + * <p> + * Accepted inputs: + * <ul> + * <li> null → null + * <li> {@link CompressedData} object + * <li> {@link org.bouncycastle.asn1.ASN1Sequence#getInstance(java.lang.Object) ASN1Sequence} input formats with CompressedData structure inside + * </ul> + * + * @param obj the object we want converted. + * @exception IllegalArgumentException if the object cannot be converted. + */ + public static CompressedData getInstance( + Object obj) + { + if (obj instanceof CompressedData) + { + return (CompressedData)obj; + } + + if (obj != null) + { + return new CompressedData(ASN1Sequence.getInstance(obj)); + } + + return null; + } + + public ASN1Integer getVersion() + { + return version; + } + + public AlgorithmIdentifier getCompressionAlgorithmIdentifier() + { + return compressionAlgorithm; + } + + public ContentInfo getEncapContentInfo() + { + return encapContentInfo; + } + + public ASN1Primitive toASN1Primitive() + { + ASN1EncodableVector v = new ASN1EncodableVector(); + + v.add(version); + v.add(compressionAlgorithm); + v.add(encapContentInfo); + + return new BERSequence(v); + } +} diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/cms/CompressedDataParser.java b/bcprov/src/main/java/org/bouncycastle/asn1/cms/CompressedDataParser.java new file mode 100644 index 0000000..41895ce --- /dev/null +++ b/bcprov/src/main/java/org/bouncycastle/asn1/cms/CompressedDataParser.java @@ -0,0 +1,49 @@ +package org.bouncycastle.asn1.cms; + +import java.io.IOException; + +import org.bouncycastle.asn1.ASN1Integer; +import org.bouncycastle.asn1.ASN1SequenceParser; +import org.bouncycastle.asn1.x509.AlgorithmIdentifier; + +/** + * Parser of <a href="http://tools.ietf.org/html/rfc3274">RFC 3274</a> {@link CompressedData} object. + * <p> + * <pre> + * CompressedData ::= SEQUENCE { + * version CMSVersion, + * compressionAlgorithm CompressionAlgorithmIdentifier, + * encapContentInfo EncapsulatedContentInfo + * } + * </pre> + */ +public class CompressedDataParser +{ + private ASN1Integer _version; + private AlgorithmIdentifier _compressionAlgorithm; + private ContentInfoParser _encapContentInfo; + + public CompressedDataParser( + ASN1SequenceParser seq) + throws IOException + { + this._version = (ASN1Integer)seq.readObject(); + this._compressionAlgorithm = AlgorithmIdentifier.getInstance(seq.readObject().toASN1Primitive()); + this._encapContentInfo = new ContentInfoParser((ASN1SequenceParser)seq.readObject()); + } + + public ASN1Integer getVersion() + { + return _version; + } + + public AlgorithmIdentifier getCompressionAlgorithmIdentifier() + { + return _compressionAlgorithm; + } + + public ContentInfoParser getEncapContentInfo() + { + return _encapContentInfo; + } +} diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/cms/ContentInfo.java b/bcprov/src/main/java/org/bouncycastle/asn1/cms/ContentInfo.java index 1592c75..2e8e039 100644 --- a/bcprov/src/main/java/org/bouncycastle/asn1/cms/ContentInfo.java +++ b/bcprov/src/main/java/org/bouncycastle/asn1/cms/ContentInfo.java @@ -28,9 +28,7 @@ import org.bouncycastle.asn1.BERTaggedObject; */ public class ContentInfo extends ASN1Object - // BEGIN android-removed - // implements CMSObjectIdentifiers - // END android-removed + implements CMSObjectIdentifiers { private ASN1ObjectIdentifier contentType; private ASN1Encodable content; diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/cms/ContentInfoParser.java b/bcprov/src/main/java/org/bouncycastle/asn1/cms/ContentInfoParser.java new file mode 100644 index 0000000..19f0ec8 --- /dev/null +++ b/bcprov/src/main/java/org/bouncycastle/asn1/cms/ContentInfoParser.java @@ -0,0 +1,48 @@ +package org.bouncycastle.asn1.cms; + +import java.io.IOException; + +import org.bouncycastle.asn1.ASN1Encodable; +import org.bouncycastle.asn1.ASN1ObjectIdentifier; +import org.bouncycastle.asn1.ASN1SequenceParser; +import org.bouncycastle.asn1.ASN1TaggedObjectParser; + +/** + * <a href="http://tools.ietf.org/html/rfc5652#section-3">RFC 5652</a> {@link ContentInfo} object parser. + * + * <pre> + * ContentInfo ::= SEQUENCE { + * contentType ContentType, + * content [0] EXPLICIT ANY DEFINED BY contentType OPTIONAL } + * </pre> + */ +public class ContentInfoParser +{ + private ASN1ObjectIdentifier contentType; + private ASN1TaggedObjectParser content; + + public ContentInfoParser( + ASN1SequenceParser seq) + throws IOException + { + contentType = (ASN1ObjectIdentifier)seq.readObject(); + content = (ASN1TaggedObjectParser)seq.readObject(); + } + + public ASN1ObjectIdentifier getContentType() + { + return contentType; + } + + public ASN1Encodable getContent( + int tag) + throws IOException + { + if (content != null) + { + return content.getObjectParser(tag, true); + } + + return null; + } +} diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/cms/DigestedData.java b/bcprov/src/main/java/org/bouncycastle/asn1/cms/DigestedData.java new file mode 100644 index 0000000..0f3b906 --- /dev/null +++ b/bcprov/src/main/java/org/bouncycastle/asn1/cms/DigestedData.java @@ -0,0 +1,128 @@ +package org.bouncycastle.asn1.cms; + +import org.bouncycastle.asn1.ASN1EncodableVector; +import org.bouncycastle.asn1.ASN1Integer; +import org.bouncycastle.asn1.ASN1Object; +import org.bouncycastle.asn1.ASN1OctetString; +import org.bouncycastle.asn1.ASN1Primitive; +import org.bouncycastle.asn1.ASN1Sequence; +import org.bouncycastle.asn1.ASN1TaggedObject; +import org.bouncycastle.asn1.BERSequence; +import org.bouncycastle.asn1.DEROctetString; +import org.bouncycastle.asn1.x509.AlgorithmIdentifier; + +/** + * <a href="http://tools.ietf.org/html/rfc5652#section-7">RFC 5652</a> DigestedData object. + * <pre> + * DigestedData ::= SEQUENCE { + * version CMSVersion, + * digestAlgorithm DigestAlgorithmIdentifier, + * encapContentInfo EncapsulatedContentInfo, + * digest Digest } + * </pre> + */ +public class DigestedData + extends ASN1Object +{ + private ASN1Integer version; + private AlgorithmIdentifier digestAlgorithm; + private ContentInfo encapContentInfo; + private ASN1OctetString digest; + + public DigestedData( + AlgorithmIdentifier digestAlgorithm, + ContentInfo encapContentInfo, + byte[] digest) + { + this.version = new ASN1Integer(0); + this.digestAlgorithm = digestAlgorithm; + this.encapContentInfo = encapContentInfo; + this.digest = new DEROctetString(digest); + } + + private DigestedData( + ASN1Sequence seq) + { + this.version = (ASN1Integer)seq.getObjectAt(0); + this.digestAlgorithm = AlgorithmIdentifier.getInstance(seq.getObjectAt(1)); + this.encapContentInfo = ContentInfo.getInstance(seq.getObjectAt(2)); + this.digest = ASN1OctetString.getInstance(seq.getObjectAt(3)); + } + + /** + * Return a DigestedData object from a tagged object. + * + * @param ato the tagged object holding the object we want. + * @param isExplicit true if the object is meant to be explicitly + * tagged false otherwise. + * @exception IllegalArgumentException if the object held by the + * tagged object cannot be converted. + */ + public static DigestedData getInstance( + ASN1TaggedObject ato, + boolean isExplicit) + { + return getInstance(ASN1Sequence.getInstance(ato, isExplicit)); + } + + /** + * Return a DigestedData object from the given object. + * <p> + * Accepted inputs: + * <ul> + * <li> null → null + * <li> {@link DigestedData} object + * <li> {@link org.bouncycastle.asn1.ASN1Sequence#getInstance(java.lang.Object) ASN1Sequence} input formats + * </ul> + * + * @param obj the object we want converted. + * @exception IllegalArgumentException if the object cannot be converted. + */ + public static DigestedData getInstance( + Object obj) + { + if (obj instanceof DigestedData) + { + return (DigestedData)obj; + } + + if (obj != null) + { + return new DigestedData(ASN1Sequence.getInstance(obj)); + } + + return null; + } + + public ASN1Integer getVersion() + { + return version; + } + + public AlgorithmIdentifier getDigestAlgorithm() + { + return digestAlgorithm; + } + + public ContentInfo getEncapContentInfo() + { + return encapContentInfo; + } + + public ASN1Primitive toASN1Primitive() + { + ASN1EncodableVector v = new ASN1EncodableVector(); + + v.add(version); + v.add(digestAlgorithm); + v.add(encapContentInfo); + v.add(digest); + + return new BERSequence(v); + } + + public byte[] getDigest() + { + return digest.getOctets(); + } +} diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/cms/EncryptedContentInfo.java b/bcprov/src/main/java/org/bouncycastle/asn1/cms/EncryptedContentInfo.java new file mode 100644 index 0000000..64d887d --- /dev/null +++ b/bcprov/src/main/java/org/bouncycastle/asn1/cms/EncryptedContentInfo.java @@ -0,0 +1,120 @@ +package org.bouncycastle.asn1.cms; + +import org.bouncycastle.asn1.ASN1EncodableVector; +import org.bouncycastle.asn1.ASN1Object; +import org.bouncycastle.asn1.ASN1ObjectIdentifier; +import org.bouncycastle.asn1.ASN1OctetString; +import org.bouncycastle.asn1.ASN1Primitive; +import org.bouncycastle.asn1.ASN1Sequence; +import org.bouncycastle.asn1.ASN1TaggedObject; +import org.bouncycastle.asn1.BERSequence; +import org.bouncycastle.asn1.BERTaggedObject; +import org.bouncycastle.asn1.x509.AlgorithmIdentifier; + +/** + * <a href="http://tools.ietf.org/html/rfc5652#section-6.1">RFC 5652</a> EncryptedContentInfo object. + * + * <pre> + * EncryptedContentInfo ::= SEQUENCE { + * contentType ContentType, + * contentEncryptionAlgorithm ContentEncryptionAlgorithmIdentifier, + * encryptedContent [0] IMPLICIT EncryptedContent OPTIONAL + * } + * </pre> + */ +public class EncryptedContentInfo + extends ASN1Object +{ + private ASN1ObjectIdentifier contentType; + private AlgorithmIdentifier contentEncryptionAlgorithm; + private ASN1OctetString encryptedContent; + + public EncryptedContentInfo( + ASN1ObjectIdentifier contentType, + AlgorithmIdentifier contentEncryptionAlgorithm, + ASN1OctetString encryptedContent) + { + this.contentType = contentType; + this.contentEncryptionAlgorithm = contentEncryptionAlgorithm; + this.encryptedContent = encryptedContent; + } + + private EncryptedContentInfo( + ASN1Sequence seq) + { + if (seq.size() < 2) + { + throw new IllegalArgumentException("Truncated Sequence Found"); + } + + contentType = (ASN1ObjectIdentifier)seq.getObjectAt(0); + contentEncryptionAlgorithm = AlgorithmIdentifier.getInstance( + seq.getObjectAt(1)); + if (seq.size() > 2) + { + encryptedContent = ASN1OctetString.getInstance( + (ASN1TaggedObject)seq.getObjectAt(2), false); + } + } + + /** + * Return an EncryptedContentInfo object from the given object. + * <p> + * Accepted inputs: + * <ul> + * <li> null → null + * <li> {@link EncryptedContentInfo} object + * <li> {@link org.bouncycastle.asn1.ASN1Sequence#getInstance(java.lang.Object) ASN1Sequence} input formats + * </ul> + * + * @param obj the object we want converted. + * @exception IllegalArgumentException if the object cannot be converted. + */ + public static EncryptedContentInfo getInstance( + Object obj) + { + if (obj instanceof EncryptedContentInfo) + { + return (EncryptedContentInfo)obj; + } + if (obj != null) + { + return new EncryptedContentInfo(ASN1Sequence.getInstance(obj)); + } + + return null; + } + + public ASN1ObjectIdentifier getContentType() + { + return contentType; + } + + public AlgorithmIdentifier getContentEncryptionAlgorithm() + { + return contentEncryptionAlgorithm; + } + + public ASN1OctetString getEncryptedContent() + { + return encryptedContent; + } + + /** + * Produce an object suitable for an ASN1OutputStream. + */ + public ASN1Primitive toASN1Primitive() + { + ASN1EncodableVector v = new ASN1EncodableVector(); + + v.add(contentType); + v.add(contentEncryptionAlgorithm); + + if (encryptedContent != null) + { + v.add(new BERTaggedObject(false, 0, encryptedContent)); + } + + return new BERSequence(v); + } +} diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/cms/EncryptedContentInfoParser.java b/bcprov/src/main/java/org/bouncycastle/asn1/cms/EncryptedContentInfoParser.java new file mode 100644 index 0000000..77fb0bb --- /dev/null +++ b/bcprov/src/main/java/org/bouncycastle/asn1/cms/EncryptedContentInfoParser.java @@ -0,0 +1,53 @@ +package org.bouncycastle.asn1.cms; + +import java.io.IOException; + +import org.bouncycastle.asn1.ASN1Encodable; +import org.bouncycastle.asn1.ASN1ObjectIdentifier; +import org.bouncycastle.asn1.ASN1SequenceParser; +import org.bouncycastle.asn1.ASN1TaggedObjectParser; +import org.bouncycastle.asn1.x509.AlgorithmIdentifier; + +/** + * Parser for <a href="http://tools.ietf.org/html/rfc5652#section-6.1">RFC 5652</a> EncryptedContentInfo object. + * <p> + * <pre> + * EncryptedContentInfo ::= SEQUENCE { + * contentType ContentType, + * contentEncryptionAlgorithm ContentEncryptionAlgorithmIdentifier, + * encryptedContent [0] IMPLICIT EncryptedContent OPTIONAL + * } + * </pre> + */ +public class EncryptedContentInfoParser +{ + private ASN1ObjectIdentifier _contentType; + private AlgorithmIdentifier _contentEncryptionAlgorithm; + private ASN1TaggedObjectParser _encryptedContent; + + public EncryptedContentInfoParser( + ASN1SequenceParser seq) + throws IOException + { + _contentType = (ASN1ObjectIdentifier)seq.readObject(); + _contentEncryptionAlgorithm = AlgorithmIdentifier.getInstance(seq.readObject().toASN1Primitive()); + _encryptedContent = (ASN1TaggedObjectParser)seq.readObject(); + } + + public ASN1ObjectIdentifier getContentType() + { + return _contentType; + } + + public AlgorithmIdentifier getContentEncryptionAlgorithm() + { + return _contentEncryptionAlgorithm; + } + + public ASN1Encodable getEncryptedContent( + int tag) + throws IOException + { + return _encryptedContent.getObjectParser(tag, false); + } +} diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/cms/EncryptedData.java b/bcprov/src/main/java/org/bouncycastle/asn1/cms/EncryptedData.java new file mode 100644 index 0000000..080abfc --- /dev/null +++ b/bcprov/src/main/java/org/bouncycastle/asn1/cms/EncryptedData.java @@ -0,0 +1,112 @@ +package org.bouncycastle.asn1.cms; + +import org.bouncycastle.asn1.ASN1EncodableVector; +import org.bouncycastle.asn1.ASN1Integer; +import org.bouncycastle.asn1.ASN1Object; +import org.bouncycastle.asn1.ASN1Primitive; +import org.bouncycastle.asn1.ASN1Sequence; +import org.bouncycastle.asn1.ASN1Set; +import org.bouncycastle.asn1.ASN1TaggedObject; +import org.bouncycastle.asn1.BERSequence; +import org.bouncycastle.asn1.BERTaggedObject; + +/** + * <a href="http://tools.ietf.org/html/rfc5652#section-8">RFC 5652</a> EncryptedData object. + * <p> + * <pre> + * EncryptedData ::= SEQUENCE { + * version CMSVersion, + * encryptedContentInfo EncryptedContentInfo, + * unprotectedAttrs [1] IMPLICIT UnprotectedAttributes OPTIONAL } + * </pre> + */ +public class EncryptedData + extends ASN1Object +{ + private ASN1Integer version; + private EncryptedContentInfo encryptedContentInfo; + private ASN1Set unprotectedAttrs; + + /** + * Return an EncryptedData object from the given object. + * <p> + * Accepted inputs: + * <ul> + * <li> null → null + * <li> {@link EncryptedData} object + * <li> {@link org.bouncycastle.asn1.ASN1Sequence#getInstance(java.lang.Object) ASN1Sequence} input formats + * </ul> + * + * @param o the object we want converted. + * @exception IllegalArgumentException if the object cannot be converted. + */ + public static EncryptedData getInstance(Object o) + { + if (o instanceof EncryptedData) + { + return (EncryptedData)o; + } + + if (o != null) + { + return new EncryptedData(ASN1Sequence.getInstance(o)); + } + + return null; + } + + public EncryptedData(EncryptedContentInfo encInfo) + { + this(encInfo, null); + } + + public EncryptedData(EncryptedContentInfo encInfo, ASN1Set unprotectedAttrs) + { + this.version = new ASN1Integer((unprotectedAttrs == null) ? 0 : 2); + this.encryptedContentInfo = encInfo; + this.unprotectedAttrs = unprotectedAttrs; + } + + private EncryptedData(ASN1Sequence seq) + { + this.version = ASN1Integer.getInstance(seq.getObjectAt(0)); + this.encryptedContentInfo = EncryptedContentInfo.getInstance(seq.getObjectAt(1)); + + if (seq.size() == 3) + { + this.unprotectedAttrs = ASN1Set.getInstance((ASN1TaggedObject)seq.getObjectAt(2), false); + } + } + + public ASN1Integer getVersion() + { + return version; + } + + public EncryptedContentInfo getEncryptedContentInfo() + { + return encryptedContentInfo; + } + + public ASN1Set getUnprotectedAttrs() + { + return unprotectedAttrs; + } + + /** + * @return a basic ASN.1 object representation. + */ + public ASN1Primitive toASN1Primitive() + { + ASN1EncodableVector v = new ASN1EncodableVector(); + + v.add(version); + v.add(encryptedContentInfo); + if (unprotectedAttrs != null) + { + v.add(new BERTaggedObject(false, 1, unprotectedAttrs)); + } + + return new BERSequence(v); + } +} diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/cms/EnvelopedData.java b/bcprov/src/main/java/org/bouncycastle/asn1/cms/EnvelopedData.java new file mode 100644 index 0000000..994575a --- /dev/null +++ b/bcprov/src/main/java/org/bouncycastle/asn1/cms/EnvelopedData.java @@ -0,0 +1,215 @@ +package org.bouncycastle.asn1.cms; + +import java.util.Enumeration; + +import org.bouncycastle.asn1.ASN1EncodableVector; +import org.bouncycastle.asn1.ASN1Integer; +import org.bouncycastle.asn1.ASN1Object; +import org.bouncycastle.asn1.ASN1Primitive; +import org.bouncycastle.asn1.ASN1Sequence; +import org.bouncycastle.asn1.ASN1Set; +import org.bouncycastle.asn1.ASN1TaggedObject; +import org.bouncycastle.asn1.BERSequence; +import org.bouncycastle.asn1.DERTaggedObject; + +/** + * <a href="http://tools.ietf.org/html/rfc5652#section-6.1">RFC 5652</a> EnvelopedData object. + * <pre> + * EnvelopedData ::= SEQUENCE { + * version CMSVersion, + * originatorInfo [0] IMPLICIT OriginatorInfo OPTIONAL, + * recipientInfos RecipientInfos, + * encryptedContentInfo EncryptedContentInfo, + * unprotectedAttrs [1] IMPLICIT UnprotectedAttributes OPTIONAL + * } + * </pre> + */ +public class EnvelopedData + extends ASN1Object +{ + private ASN1Integer version; + private OriginatorInfo originatorInfo; + private ASN1Set recipientInfos; + private EncryptedContentInfo encryptedContentInfo; + private ASN1Set unprotectedAttrs; + + public EnvelopedData( + OriginatorInfo originatorInfo, + ASN1Set recipientInfos, + EncryptedContentInfo encryptedContentInfo, + ASN1Set unprotectedAttrs) + { + version = new ASN1Integer(calculateVersion(originatorInfo, recipientInfos, unprotectedAttrs)); + + this.originatorInfo = originatorInfo; + this.recipientInfos = recipientInfos; + this.encryptedContentInfo = encryptedContentInfo; + this.unprotectedAttrs = unprotectedAttrs; + } + + public EnvelopedData( + OriginatorInfo originatorInfo, + ASN1Set recipientInfos, + EncryptedContentInfo encryptedContentInfo, + Attributes unprotectedAttrs) + { + version = new ASN1Integer(calculateVersion(originatorInfo, recipientInfos, ASN1Set.getInstance(unprotectedAttrs))); + + this.originatorInfo = originatorInfo; + this.recipientInfos = recipientInfos; + this.encryptedContentInfo = encryptedContentInfo; + this.unprotectedAttrs = ASN1Set.getInstance(unprotectedAttrs); + } + + /** + * @deprecated use getInstance() + */ + public EnvelopedData( + ASN1Sequence seq) + { + int index = 0; + + version = (ASN1Integer)seq.getObjectAt(index++); + + Object tmp = seq.getObjectAt(index++); + + if (tmp instanceof ASN1TaggedObject) + { + originatorInfo = OriginatorInfo.getInstance((ASN1TaggedObject)tmp, false); + tmp = seq.getObjectAt(index++); + } + + recipientInfos = ASN1Set.getInstance(tmp); + + encryptedContentInfo = EncryptedContentInfo.getInstance(seq.getObjectAt(index++)); + + if(seq.size() > index) + { + unprotectedAttrs = ASN1Set.getInstance((ASN1TaggedObject)seq.getObjectAt(index), false); + } + } + + /** + * Return an EnvelopedData object from a tagged object. + * + * @param obj the tagged object holding the object we want. + * @param explicit true if the object is meant to be explicitly + * tagged false otherwise. + * @exception IllegalArgumentException if the object held by the + * tagged object cannot be converted. + */ + public static EnvelopedData getInstance( + ASN1TaggedObject obj, + boolean explicit) + { + return getInstance(ASN1Sequence.getInstance(obj, explicit)); + } + + /** + * Return an EnvelopedData object from the given object. + * <p> + * Accepted inputs: + * <ul> + * <li> null → null + * <li> {@link EnvelopedData} object + * <li> {@link org.bouncycastle.asn1.ASN1Sequence#getInstance(java.lang.Object) ASN1Sequence} input formats with EnvelopedData structure inside + * </ul> + * + * @param obj the object we want converted. + * @exception IllegalArgumentException if the object cannot be converted. + */ + public static EnvelopedData getInstance( + Object obj) + { + if (obj instanceof EnvelopedData) + { + return (EnvelopedData)obj; + } + + if (obj != null) + { + return new EnvelopedData(ASN1Sequence.getInstance(obj)); + } + + return null; + } + + public ASN1Integer getVersion() + { + return version; + } + + public OriginatorInfo getOriginatorInfo() + { + return originatorInfo; + } + + public ASN1Set getRecipientInfos() + { + return recipientInfos; + } + + public EncryptedContentInfo getEncryptedContentInfo() + { + return encryptedContentInfo; + } + + public ASN1Set getUnprotectedAttrs() + { + return unprotectedAttrs; + } + + /** + * Produce an object suitable for an ASN1OutputStream. + */ + public ASN1Primitive toASN1Primitive() + { + ASN1EncodableVector v = new ASN1EncodableVector(); + + v.add(version); + + if (originatorInfo != null) + { + v.add(new DERTaggedObject(false, 0, originatorInfo)); + } + + v.add(recipientInfos); + v.add(encryptedContentInfo); + + if (unprotectedAttrs != null) + { + v.add(new DERTaggedObject(false, 1, unprotectedAttrs)); + } + + return new BERSequence(v); + } + + public static int calculateVersion(OriginatorInfo originatorInfo, ASN1Set recipientInfos, ASN1Set unprotectedAttrs) + { + int version; + + if (originatorInfo != null || unprotectedAttrs != null) + { + version = 2; + } + else + { + version = 0; + + Enumeration e = recipientInfos.getObjects(); + + while (e.hasMoreElements()) + { + RecipientInfo ri = RecipientInfo.getInstance(e.nextElement()); + + if (ri.getVersion().getValue().intValue() != version) + { + version = 2; + break; + } + } + } + + return version; + } +} diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/cms/EnvelopedDataParser.java b/bcprov/src/main/java/org/bouncycastle/asn1/cms/EnvelopedDataParser.java new file mode 100644 index 0000000..774813a --- /dev/null +++ b/bcprov/src/main/java/org/bouncycastle/asn1/cms/EnvelopedDataParser.java @@ -0,0 +1,120 @@ +package org.bouncycastle.asn1.cms; + +import java.io.IOException; + +import org.bouncycastle.asn1.ASN1Encodable; +import org.bouncycastle.asn1.ASN1Integer; +import org.bouncycastle.asn1.ASN1SequenceParser; +import org.bouncycastle.asn1.ASN1SetParser; +import org.bouncycastle.asn1.ASN1TaggedObjectParser; +import org.bouncycastle.asn1.BERTags; + +/** + * Parser of <a href="http://tools.ietf.org/html/rfc5652#section-6.1">RFC 5652</a> {@link EnvelopedData} object. + * <p> + * <pre> + * EnvelopedData ::= SEQUENCE { + * version CMSVersion, + * originatorInfo [0] IMPLICIT OriginatorInfo OPTIONAL, + * recipientInfos RecipientInfos, + * encryptedContentInfo EncryptedContentInfo, + * unprotectedAttrs [1] IMPLICIT UnprotectedAttributes OPTIONAL + * } + * </pre> + */ +public class EnvelopedDataParser +{ + private ASN1SequenceParser _seq; + private ASN1Integer _version; + private ASN1Encodable _nextObject; + private boolean _originatorInfoCalled; + + public EnvelopedDataParser( + ASN1SequenceParser seq) + throws IOException + { + this._seq = seq; + this._version = ASN1Integer.getInstance(seq.readObject()); + } + + public ASN1Integer getVersion() + { + return _version; + } + + public OriginatorInfo getOriginatorInfo() + throws IOException + { + _originatorInfoCalled = true; + + if (_nextObject == null) + { + _nextObject = _seq.readObject(); + } + + if (_nextObject instanceof ASN1TaggedObjectParser && ((ASN1TaggedObjectParser)_nextObject).getTagNo() == 0) + { + ASN1SequenceParser originatorInfo = (ASN1SequenceParser) ((ASN1TaggedObjectParser)_nextObject).getObjectParser(BERTags.SEQUENCE, false); + _nextObject = null; + return OriginatorInfo.getInstance(originatorInfo.toASN1Primitive()); + } + + return null; + } + + public ASN1SetParser getRecipientInfos() + throws IOException + { + if (!_originatorInfoCalled) + { + getOriginatorInfo(); + } + + if (_nextObject == null) + { + _nextObject = _seq.readObject(); + } + + ASN1SetParser recipientInfos = (ASN1SetParser)_nextObject; + _nextObject = null; + return recipientInfos; + } + + public EncryptedContentInfoParser getEncryptedContentInfo() + throws IOException + { + if (_nextObject == null) + { + _nextObject = _seq.readObject(); + } + + + if (_nextObject != null) + { + ASN1SequenceParser o = (ASN1SequenceParser) _nextObject; + _nextObject = null; + return new EncryptedContentInfoParser(o); + } + + return null; + } + + public ASN1SetParser getUnprotectedAttrs() + throws IOException + { + if (_nextObject == null) + { + _nextObject = _seq.readObject(); + } + + + if (_nextObject != null) + { + ASN1Encodable o = _nextObject; + _nextObject = null; + return (ASN1SetParser)((ASN1TaggedObjectParser)o).getObjectParser(BERTags.SET, false); + } + + return null; + } +} diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/cms/Evidence.java b/bcprov/src/main/java/org/bouncycastle/asn1/cms/Evidence.java new file mode 100644 index 0000000..4dcbfde --- /dev/null +++ b/bcprov/src/main/java/org/bouncycastle/asn1/cms/Evidence.java @@ -0,0 +1,80 @@ +package org.bouncycastle.asn1.cms; + +import org.bouncycastle.asn1.ASN1Choice; +import org.bouncycastle.asn1.ASN1Object; +import org.bouncycastle.asn1.ASN1Primitive; +import org.bouncycastle.asn1.ASN1TaggedObject; +import org.bouncycastle.asn1.DERTaggedObject; + +/** + * <a href="http://tools.ietf.org/html/rfc5544">RFC 5544</a>: + * Binding Documents with Time-Stamps; Evidence object. + * <p> + * <pre> + * Evidence ::= CHOICE { + * tstEvidence [0] TimeStampTokenEvidence, -- see RFC 3161 + * ersEvidence [1] EvidenceRecord, -- see RFC 4998 + * otherEvidence [2] OtherEvidence + * } + * </pre> + */ +public class Evidence + extends ASN1Object + implements ASN1Choice +{ + private TimeStampTokenEvidence tstEvidence; + + public Evidence(TimeStampTokenEvidence tstEvidence) + { + this.tstEvidence = tstEvidence; + } + + private Evidence(ASN1TaggedObject tagged) + { + if (tagged.getTagNo() == 0) + { + this.tstEvidence = TimeStampTokenEvidence.getInstance(tagged, false); + } + } + + /** + * Return an Evidence object from the given object. + * <p> + * Accepted inputs: + * <ul> + * <li> {@link Evidence} object + * <li> {@link org.bouncycastle.asn1.ASN1TaggedObject#getInstance(java.lang.Object) ASN1TaggedObject} input formats with Evidence data inside + * </ul> + * + * @param obj the object we want converted. + * @exception IllegalArgumentException if the object cannot be converted. + */ + public static Evidence getInstance(Object obj) + { + if (obj == null || obj instanceof Evidence) + { + return (Evidence)obj; + } + else if (obj instanceof ASN1TaggedObject) + { + return new Evidence(ASN1TaggedObject.getInstance(obj)); + } + + throw new IllegalArgumentException("unknown object in getInstance"); + } + + public TimeStampTokenEvidence getTstEvidence() + { + return tstEvidence; + } + + public ASN1Primitive toASN1Primitive() + { + if (tstEvidence != null) + { + return new DERTaggedObject(false, 0, tstEvidence); + } + + return null; + } +} diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/cms/KEKIdentifier.java b/bcprov/src/main/java/org/bouncycastle/asn1/cms/KEKIdentifier.java new file mode 100644 index 0000000..0361e9f --- /dev/null +++ b/bcprov/src/main/java/org/bouncycastle/asn1/cms/KEKIdentifier.java @@ -0,0 +1,151 @@ +package org.bouncycastle.asn1.cms; + +import org.bouncycastle.asn1.ASN1EncodableVector; +import org.bouncycastle.asn1.ASN1GeneralizedTime; +import org.bouncycastle.asn1.ASN1Object; +import org.bouncycastle.asn1.ASN1OctetString; +import org.bouncycastle.asn1.ASN1Primitive; +import org.bouncycastle.asn1.ASN1Sequence; +import org.bouncycastle.asn1.ASN1TaggedObject; +import org.bouncycastle.asn1.DEROctetString; +import org.bouncycastle.asn1.DERSequence; + +/** + * <a href="http://tools.ietf.org/html/rfc5652#section-6.2.3">RFC 5652</a>: + * Content encryption key delivery mechanisms. + * <p> + * <pre> + * KEKIdentifier ::= SEQUENCE { + * keyIdentifier OCTET STRING, + * date GeneralizedTime OPTIONAL, + * other OtherKeyAttribute OPTIONAL + * } + * </pre> + */ +public class KEKIdentifier + extends ASN1Object +{ + private ASN1OctetString keyIdentifier; + private ASN1GeneralizedTime date; + private OtherKeyAttribute other; + + public KEKIdentifier( + byte[] keyIdentifier, + ASN1GeneralizedTime date, + OtherKeyAttribute other) + { + this.keyIdentifier = new DEROctetString(keyIdentifier); + this.date = date; + this.other = other; + } + + private KEKIdentifier( + ASN1Sequence seq) + { + keyIdentifier = (ASN1OctetString)seq.getObjectAt(0); + + switch (seq.size()) + { + case 1: + break; + case 2: + if (seq.getObjectAt(1) instanceof ASN1GeneralizedTime) + { + date = (ASN1GeneralizedTime)seq.getObjectAt(1); + } + else + { + other = OtherKeyAttribute.getInstance(seq.getObjectAt(1)); + } + break; + case 3: + date = (ASN1GeneralizedTime)seq.getObjectAt(1); + other = OtherKeyAttribute.getInstance(seq.getObjectAt(2)); + break; + default: + throw new IllegalArgumentException("Invalid KEKIdentifier"); + } + } + + /** + * Return a KEKIdentifier object from a tagged object. + * + * @param obj the tagged object holding the object we want. + * @param explicit true if the object is meant to be explicitly + * tagged false otherwise. + * @exception IllegalArgumentException if the object held by the + * tagged object cannot be converted. + */ + public static KEKIdentifier getInstance( + ASN1TaggedObject obj, + boolean explicit) + { + return getInstance(ASN1Sequence.getInstance(obj, explicit)); + } + + /** + * Return a KEKIdentifier object from the given object. + * <p> + * Accepted inputs: + * <ul> + * <li> null → null + * <li> {@link KEKIdentifier} object + * <li> {@link org.bouncycastle.asn1.ASN1Sequence#getInstance(java.lang.Object) ASN1Sequence} input formats with KEKIdentifier structure inside + * </ul> + * + * @param obj the object we want converted. + * @exception IllegalArgumentException if the object cannot be converted. + */ + public static KEKIdentifier getInstance( + Object obj) + { + if (obj == null || obj instanceof KEKIdentifier) + { + return (KEKIdentifier)obj; + } + + if (obj instanceof ASN1Sequence) + { + return new KEKIdentifier((ASN1Sequence)obj); + } + + throw new IllegalArgumentException("Invalid KEKIdentifier: " + obj.getClass().getName()); + } + + public ASN1OctetString getKeyIdentifier() + { + return keyIdentifier; + } + + public ASN1GeneralizedTime getDate() + { + return date; + } + + public OtherKeyAttribute getOther() + { + return other; + } + + /** + * Produce an object suitable for an ASN1OutputStream. + */ + public ASN1Primitive toASN1Primitive() + { + ASN1EncodableVector v = new ASN1EncodableVector(); + + v.add(keyIdentifier); + + if (date != null) + { + v.add(date); + } + + if (other != null) + { + v.add(other); + } + + return new DERSequence(v); + } +} diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/cms/KEKRecipientInfo.java b/bcprov/src/main/java/org/bouncycastle/asn1/cms/KEKRecipientInfo.java new file mode 100644 index 0000000..2d0cfa6 --- /dev/null +++ b/bcprov/src/main/java/org/bouncycastle/asn1/cms/KEKRecipientInfo.java @@ -0,0 +1,133 @@ +package org.bouncycastle.asn1.cms; + +import org.bouncycastle.asn1.ASN1EncodableVector; +import org.bouncycastle.asn1.ASN1Integer; +import org.bouncycastle.asn1.ASN1Object; +import org.bouncycastle.asn1.ASN1OctetString; +import org.bouncycastle.asn1.ASN1Primitive; +import org.bouncycastle.asn1.ASN1Sequence; +import org.bouncycastle.asn1.ASN1TaggedObject; +import org.bouncycastle.asn1.DERSequence; +import org.bouncycastle.asn1.x509.AlgorithmIdentifier; + +/** + * <a href="http://tools.ietf.org/html/rfc5652#section-6.2.3">RFC 5652</a>: + * Content encryption key delivery mechanisms. + * <p> + * <pre> + * KEKRecipientInfo ::= SEQUENCE { + * version CMSVersion, -- always set to 4 + * kekid KEKIdentifier, + * keyEncryptionAlgorithm KeyEncryptionAlgorithmIdentifier, + * encryptedKey EncryptedKey + * } + * </pre> + */ +public class KEKRecipientInfo + extends ASN1Object +{ + private ASN1Integer version; + private KEKIdentifier kekid; + private AlgorithmIdentifier keyEncryptionAlgorithm; + private ASN1OctetString encryptedKey; + + public KEKRecipientInfo( + KEKIdentifier kekid, + AlgorithmIdentifier keyEncryptionAlgorithm, + ASN1OctetString encryptedKey) + { + this.version = new ASN1Integer(4); + this.kekid = kekid; + this.keyEncryptionAlgorithm = keyEncryptionAlgorithm; + this.encryptedKey = encryptedKey; + } + + public KEKRecipientInfo( + ASN1Sequence seq) + { + version = (ASN1Integer)seq.getObjectAt(0); + kekid = KEKIdentifier.getInstance(seq.getObjectAt(1)); + keyEncryptionAlgorithm = AlgorithmIdentifier.getInstance(seq.getObjectAt(2)); + encryptedKey = (ASN1OctetString)seq.getObjectAt(3); + } + + /** + * Return a KEKRecipientInfo object from a tagged object. + * + * @param obj the tagged object holding the object we want. + * @param explicit true if the object is meant to be explicitly + * tagged false otherwise. + * @exception IllegalArgumentException if the object held by the + * tagged object cannot be converted. + */ + public static KEKRecipientInfo getInstance( + ASN1TaggedObject obj, + boolean explicit) + { + return getInstance(ASN1Sequence.getInstance(obj, explicit)); + } + + /** + * Return a KEKRecipientInfo object from the given object. + * <p> + * Accepted inputs: + * <ul> + * <li> null → null + * <li> {@link KEKRecipientInfo} object + * <li> {@link org.bouncycastle.asn1.ASN1Sequence#getInstance(java.lang.Object) ASN1Sequence} input formats with KEKRecipientInfo structure inside + * </ul> + * + * @param obj the object we want converted. + * @exception IllegalArgumentException if the object cannot be converted. + */ + public static KEKRecipientInfo getInstance( + Object obj) + { + if (obj instanceof KEKRecipientInfo) + { + return (KEKRecipientInfo)obj; + } + + if (obj != null) + { + return new KEKRecipientInfo(ASN1Sequence.getInstance(obj)); + } + + return null; + } + + public ASN1Integer getVersion() + { + return version; + } + + public KEKIdentifier getKekid() + { + return kekid; + } + + public AlgorithmIdentifier getKeyEncryptionAlgorithm() + { + return keyEncryptionAlgorithm; + } + + public ASN1OctetString getEncryptedKey() + { + return encryptedKey; + } + + /** + * Produce an object suitable for an ASN1OutputStream. + */ + public ASN1Primitive toASN1Primitive() + { + ASN1EncodableVector v = new ASN1EncodableVector(); + + v.add(version); + v.add(kekid); + v.add(keyEncryptionAlgorithm); + v.add(encryptedKey); + + return new DERSequence(v); + } +} diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/cms/KeyAgreeRecipientIdentifier.java b/bcprov/src/main/java/org/bouncycastle/asn1/cms/KeyAgreeRecipientIdentifier.java new file mode 100644 index 0000000..6580cd4 --- /dev/null +++ b/bcprov/src/main/java/org/bouncycastle/asn1/cms/KeyAgreeRecipientIdentifier.java @@ -0,0 +1,116 @@ +package org.bouncycastle.asn1.cms; + +import org.bouncycastle.asn1.ASN1Choice; +import org.bouncycastle.asn1.ASN1Object; +import org.bouncycastle.asn1.ASN1Primitive; +import org.bouncycastle.asn1.ASN1Sequence; +import org.bouncycastle.asn1.ASN1TaggedObject; +import org.bouncycastle.asn1.DERTaggedObject; + +/** + * <a href="http://tools.ietf.org/html/rfc5652#section-6.2.2">RFC 5652</a>: + * Content encryption key delivery mechanisms. + * <p> + * <pre> + * KeyAgreeRecipientIdentifier ::= CHOICE { + * issuerAndSerialNumber IssuerAndSerialNumber, + * rKeyId [0] IMPLICIT RecipientKeyIdentifier } + * </pre> + */ +public class KeyAgreeRecipientIdentifier + extends ASN1Object + implements ASN1Choice +{ + private IssuerAndSerialNumber issuerSerial; + private RecipientKeyIdentifier rKeyID; + + /** + * Return an KeyAgreeRecipientIdentifier object from a tagged object. + * + * @param obj the tagged object holding the object we want. + * @param explicit true if the object is meant to be explicitly + * tagged false otherwise. + * @exception IllegalArgumentException if the object held by the + * tagged object cannot be converted. + */ + public static KeyAgreeRecipientIdentifier getInstance( + ASN1TaggedObject obj, + boolean explicit) + { + return getInstance(ASN1Sequence.getInstance(obj, explicit)); + } + + /** + * Return an KeyAgreeRecipientIdentifier object from the given object. + * <p> + * Accepted inputs: + * <ul> + * <li> {@link KeyAgreeRecipientIdentifier} object + * <li> {@link org.bouncycastle.asn1.ASN1Sequence#getInstance(java.lang.Object) ASN1Sequence} input formats with IssuerAndSerialNumber structure inside + * <li> {@link org.bouncycastle.asn1.ASN1TaggedObject#getInstance(java.lang.Object) ASN1TaggedObject} with tag value 0: a KeyAgreeRecipientIdentifier data structure + * </ul> + * <p> + * Note: no byte[] input! + * + * @param obj the object we want converted. + * @exception IllegalArgumentException if the object cannot be converted. + */ + public static KeyAgreeRecipientIdentifier getInstance( + Object obj) + { + if (obj == null || obj instanceof KeyAgreeRecipientIdentifier) + { + return (KeyAgreeRecipientIdentifier)obj; + } + + if (obj instanceof ASN1Sequence) + { + return new KeyAgreeRecipientIdentifier(IssuerAndSerialNumber.getInstance(obj)); + } + + if (obj instanceof ASN1TaggedObject && ((ASN1TaggedObject)obj).getTagNo() == 0) + { + return new KeyAgreeRecipientIdentifier(RecipientKeyIdentifier.getInstance( + (ASN1TaggedObject)obj, false)); + } + + throw new IllegalArgumentException("Invalid KeyAgreeRecipientIdentifier: " + obj.getClass().getName()); + } + + public KeyAgreeRecipientIdentifier( + IssuerAndSerialNumber issuerSerial) + { + this.issuerSerial = issuerSerial; + this.rKeyID = null; + } + + public KeyAgreeRecipientIdentifier( + RecipientKeyIdentifier rKeyID) + { + this.issuerSerial = null; + this.rKeyID = rKeyID; + } + + public IssuerAndSerialNumber getIssuerAndSerialNumber() + { + return issuerSerial; + } + + public RecipientKeyIdentifier getRKeyID() + { + return rKeyID; + } + + /** + * Produce an object suitable for an ASN1OutputStream. + */ + public ASN1Primitive toASN1Primitive() + { + if (issuerSerial != null) + { + return issuerSerial.toASN1Primitive(); + } + + return new DERTaggedObject(false, 0, rKeyID); + } +} diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/cms/KeyAgreeRecipientInfo.java b/bcprov/src/main/java/org/bouncycastle/asn1/cms/KeyAgreeRecipientInfo.java new file mode 100644 index 0000000..224932a --- /dev/null +++ b/bcprov/src/main/java/org/bouncycastle/asn1/cms/KeyAgreeRecipientInfo.java @@ -0,0 +1,166 @@ +package org.bouncycastle.asn1.cms; + +import org.bouncycastle.asn1.ASN1EncodableVector; +import org.bouncycastle.asn1.ASN1Integer; +import org.bouncycastle.asn1.ASN1Object; +import org.bouncycastle.asn1.ASN1OctetString; +import org.bouncycastle.asn1.ASN1Primitive; +import org.bouncycastle.asn1.ASN1Sequence; +import org.bouncycastle.asn1.ASN1TaggedObject; +import org.bouncycastle.asn1.DERSequence; +import org.bouncycastle.asn1.DERTaggedObject; +import org.bouncycastle.asn1.x509.AlgorithmIdentifier; + +/** + * <a href="http://tools.ietf.org/html/rfc5652#section-6.2.2">RFC 5652</a>: + * Content encryption key delivery mechanisms. + * <p> + * <pre> + * KeyAgreeRecipientInfo ::= SEQUENCE { + * version CMSVersion, -- always set to 3 + * originator [0] EXPLICIT OriginatorIdentifierOrKey, + * ukm [1] EXPLICIT UserKeyingMaterial OPTIONAL, + * keyEncryptionAlgorithm KeyEncryptionAlgorithmIdentifier, + * recipientEncryptedKeys RecipientEncryptedKeys + * } + * + * UserKeyingMaterial ::= OCTET STRING + * </pre> + */ +public class KeyAgreeRecipientInfo + extends ASN1Object +{ + private ASN1Integer version; + private OriginatorIdentifierOrKey originator; + private ASN1OctetString ukm; + private AlgorithmIdentifier keyEncryptionAlgorithm; + private ASN1Sequence recipientEncryptedKeys; + + public KeyAgreeRecipientInfo( + OriginatorIdentifierOrKey originator, + ASN1OctetString ukm, + AlgorithmIdentifier keyEncryptionAlgorithm, + ASN1Sequence recipientEncryptedKeys) + { + this.version = new ASN1Integer(3); + this.originator = originator; + this.ukm = ukm; + this.keyEncryptionAlgorithm = keyEncryptionAlgorithm; + this.recipientEncryptedKeys = recipientEncryptedKeys; + } + + /** + * @deprecated use getInstance() + */ + public KeyAgreeRecipientInfo( + ASN1Sequence seq) + { + int index = 0; + + version = (ASN1Integer)seq.getObjectAt(index++); + originator = OriginatorIdentifierOrKey.getInstance( + (ASN1TaggedObject)seq.getObjectAt(index++), true); + + if (seq.getObjectAt(index) instanceof ASN1TaggedObject) + { + ukm = ASN1OctetString.getInstance( + (ASN1TaggedObject)seq.getObjectAt(index++), true); + } + + keyEncryptionAlgorithm = AlgorithmIdentifier.getInstance( + seq.getObjectAt(index++)); + + recipientEncryptedKeys = (ASN1Sequence)seq.getObjectAt(index++); + } + + /** + * Return a KeyAgreeRecipientInfo object from a tagged object. + * + * @param obj the tagged object holding the object we want. + * @param explicit true if the object is meant to be explicitly + * tagged false otherwise. + * @exception IllegalArgumentException if the object held by the + * tagged object cannot be converted. + */ + public static KeyAgreeRecipientInfo getInstance( + ASN1TaggedObject obj, + boolean explicit) + { + return getInstance(ASN1Sequence.getInstance(obj, explicit)); + } + + /** + * Return a KeyAgreeRecipientInfo object from the given object. + * <p> + * Accepted inputs: + * <ul> + * <li> null → null + * <li> {@link KeyAgreeRecipientInfo} object + * <li> {@link org.bouncycastle.asn1.ASN1Sequence#getInstance(java.lang.Object) ASN1Sequence} input formats with KeyAgreeRecipientInfo structure inside + * </ul> + * + * @param obj the object we want converted. + * @exception IllegalArgumentException if the object cannot be converted. + */ + public static KeyAgreeRecipientInfo getInstance( + Object obj) + { + if (obj instanceof KeyAgreeRecipientInfo) + { + return (KeyAgreeRecipientInfo)obj; + } + + if (obj != null) + { + return new KeyAgreeRecipientInfo(ASN1Sequence.getInstance(obj)); + } + + return null; + } + + public ASN1Integer getVersion() + { + return version; + } + + public OriginatorIdentifierOrKey getOriginator() + { + return originator; + } + + public ASN1OctetString getUserKeyingMaterial() + { + return ukm; + } + + public AlgorithmIdentifier getKeyEncryptionAlgorithm() + { + return keyEncryptionAlgorithm; + } + + public ASN1Sequence getRecipientEncryptedKeys() + { + return recipientEncryptedKeys; + } + + /** + * Produce an object suitable for an ASN1OutputStream. + */ + public ASN1Primitive toASN1Primitive() + { + ASN1EncodableVector v = new ASN1EncodableVector(); + + v.add(version); + v.add(new DERTaggedObject(true, 0, originator)); + + if (ukm != null) + { + v.add(new DERTaggedObject(true, 1, ukm)); + } + + v.add(keyEncryptionAlgorithm); + v.add(recipientEncryptedKeys); + + return new DERSequence(v); + } +} diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/cms/KeyTransRecipientInfo.java b/bcprov/src/main/java/org/bouncycastle/asn1/cms/KeyTransRecipientInfo.java new file mode 100644 index 0000000..7d31111 --- /dev/null +++ b/bcprov/src/main/java/org/bouncycastle/asn1/cms/KeyTransRecipientInfo.java @@ -0,0 +1,127 @@ +package org.bouncycastle.asn1.cms; + +import org.bouncycastle.asn1.ASN1EncodableVector; +import org.bouncycastle.asn1.ASN1Integer; +import org.bouncycastle.asn1.ASN1Object; +import org.bouncycastle.asn1.ASN1OctetString; +import org.bouncycastle.asn1.ASN1Primitive; +import org.bouncycastle.asn1.ASN1Sequence; +import org.bouncycastle.asn1.ASN1TaggedObject; +import org.bouncycastle.asn1.DERSequence; +import org.bouncycastle.asn1.x509.AlgorithmIdentifier; + +/** + * <a href="http://tools.ietf.org/html/rfc5652#section-6.2.1">RFC 5652</a>: + * Content encryption key delivery mechanisms. + * <pre> + * KeyTransRecipientInfo ::= SEQUENCE { + * version CMSVersion, -- always set to 0 or 2 + * rid RecipientIdentifier, + * keyEncryptionAlgorithm KeyEncryptionAlgorithmIdentifier, + * encryptedKey EncryptedKey + * } + * </pre> + */ +public class KeyTransRecipientInfo + extends ASN1Object +{ + private ASN1Integer version; + private RecipientIdentifier rid; + private AlgorithmIdentifier keyEncryptionAlgorithm; + private ASN1OctetString encryptedKey; + + public KeyTransRecipientInfo( + RecipientIdentifier rid, + AlgorithmIdentifier keyEncryptionAlgorithm, + ASN1OctetString encryptedKey) + { + if (rid.toASN1Primitive() instanceof ASN1TaggedObject) + { + this.version = new ASN1Integer(2); + } + else + { + this.version = new ASN1Integer(0); + } + + this.rid = rid; + this.keyEncryptionAlgorithm = keyEncryptionAlgorithm; + this.encryptedKey = encryptedKey; + } + + /** + * @deprecated use getInstance() + */ + public KeyTransRecipientInfo( + ASN1Sequence seq) + { + this.version = (ASN1Integer)seq.getObjectAt(0); + this.rid = RecipientIdentifier.getInstance(seq.getObjectAt(1)); + this.keyEncryptionAlgorithm = AlgorithmIdentifier.getInstance(seq.getObjectAt(2)); + this.encryptedKey = (ASN1OctetString)seq.getObjectAt(3); + } + + /** + * Return a KeyTransRecipientInfo object from the given object. + * <p> + * Accepted inputs: + * <ul> + * <li> null → null + * <li> {@link KeyTransRecipientInfo} object + * <li> {@link org.bouncycastle.asn1.ASN1Sequence#getInstance(java.lang.Object) ASN1Sequence} input formats with KeyTransRecipientInfo structure inside + * </ul> + * + * @param obj the object we want converted. + * @exception IllegalArgumentException if the object cannot be converted. + */ + public static KeyTransRecipientInfo getInstance( + Object obj) + { + if (obj instanceof KeyTransRecipientInfo) + { + return (KeyTransRecipientInfo)obj; + } + + if(obj != null) + { + return new KeyTransRecipientInfo(ASN1Sequence.getInstance(obj)); + } + + return null; + } + + public ASN1Integer getVersion() + { + return version; + } + + public RecipientIdentifier getRecipientIdentifier() + { + return rid; + } + + public AlgorithmIdentifier getKeyEncryptionAlgorithm() + { + return keyEncryptionAlgorithm; + } + + public ASN1OctetString getEncryptedKey() + { + return encryptedKey; + } + + /** + * Produce an object suitable for an ASN1OutputStream. + */ + public ASN1Primitive toASN1Primitive() + { + ASN1EncodableVector v = new ASN1EncodableVector(); + + v.add(version); + v.add(rid); + v.add(keyEncryptionAlgorithm); + v.add(encryptedKey); + + return new DERSequence(v); + } +} diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/cms/MetaData.java b/bcprov/src/main/java/org/bouncycastle/asn1/cms/MetaData.java new file mode 100644 index 0000000..667187b --- /dev/null +++ b/bcprov/src/main/java/org/bouncycastle/asn1/cms/MetaData.java @@ -0,0 +1,135 @@ +package org.bouncycastle.asn1.cms; + +import org.bouncycastle.asn1.ASN1Boolean; +import org.bouncycastle.asn1.ASN1EncodableVector; +import org.bouncycastle.asn1.ASN1Object; +import org.bouncycastle.asn1.ASN1Primitive; +import org.bouncycastle.asn1.ASN1Sequence; +import org.bouncycastle.asn1.DERIA5String; +import org.bouncycastle.asn1.DERSequence; +import org.bouncycastle.asn1.DERUTF8String; + +/** + * <a href="http://tools.ietf.org/html/rfc5544">RFC 5544</a>: + * Binding Documents with Time-Stamps; MetaData object. + * <p> + * <pre> + * MetaData ::= SEQUENCE { + * hashProtected BOOLEAN, + * fileName UTF8String OPTIONAL, + * mediaType IA5String OPTIONAL, + * otherMetaData Attributes OPTIONAL + * } + * </pre> + */ +public class MetaData + extends ASN1Object +{ + private ASN1Boolean hashProtected; + private DERUTF8String fileName; + private DERIA5String mediaType; + private Attributes otherMetaData; + + public MetaData( + ASN1Boolean hashProtected, + DERUTF8String fileName, + DERIA5String mediaType, + Attributes otherMetaData) + { + this.hashProtected = hashProtected; + this.fileName = fileName; + this.mediaType = mediaType; + this.otherMetaData = otherMetaData; + } + + private MetaData(ASN1Sequence seq) + { + this.hashProtected = ASN1Boolean.getInstance(seq.getObjectAt(0)); + + int index = 1; + + if (index < seq.size() && seq.getObjectAt(index) instanceof DERUTF8String) + { + this.fileName = DERUTF8String.getInstance(seq.getObjectAt(index++)); + } + if (index < seq.size() && seq.getObjectAt(index) instanceof DERIA5String) + { + this.mediaType = DERIA5String.getInstance(seq.getObjectAt(index++)); + } + if (index < seq.size()) + { + this.otherMetaData = Attributes.getInstance(seq.getObjectAt(index++)); + } + } + + /** + * Return a MetaData object from the given object. + * <p> + * Accepted inputs: + * <ul> + * <li> null → null + * <li> {@link MetaData} object + * <li> {@link org.bouncycastle.asn1.ASN1Sequence#getInstance(java.lang.Object) ASN1Sequence} input formats with MetaData structure inside + * </ul> + * + * @param obj the object we want converted. + * @exception IllegalArgumentException if the object cannot be converted. + */ + public static MetaData getInstance(Object obj) + { + if (obj instanceof MetaData) + { + return (MetaData)obj; + } + else if (obj != null) + { + return new MetaData(ASN1Sequence.getInstance(obj)); + } + + return null; + } + + public ASN1Primitive toASN1Primitive() + { + ASN1EncodableVector v = new ASN1EncodableVector(); + + v.add(hashProtected); + + if (fileName != null) + { + v.add(fileName); + } + + if (mediaType != null) + { + v.add(mediaType); + } + + if (otherMetaData != null) + { + v.add(otherMetaData); + } + + return new DERSequence(v); + } + + public boolean isHashProtected() + { + return hashProtected.isTrue(); + } + + public DERUTF8String getFileName() + { + return this.fileName; + } + + public DERIA5String getMediaType() + { + return this.mediaType; + } + + public Attributes getOtherMetaData() + { + return otherMetaData; + } +} diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/cms/OriginatorIdentifierOrKey.java b/bcprov/src/main/java/org/bouncycastle/asn1/cms/OriginatorIdentifierOrKey.java new file mode 100644 index 0000000..2096be2 --- /dev/null +++ b/bcprov/src/main/java/org/bouncycastle/asn1/cms/OriginatorIdentifierOrKey.java @@ -0,0 +1,179 @@ +package org.bouncycastle.asn1.cms; + +import org.bouncycastle.asn1.ASN1Choice; +import org.bouncycastle.asn1.ASN1Encodable; +import org.bouncycastle.asn1.ASN1Object; +import org.bouncycastle.asn1.ASN1OctetString; +import org.bouncycastle.asn1.ASN1Primitive; +import org.bouncycastle.asn1.ASN1TaggedObject; +import org.bouncycastle.asn1.DERTaggedObject; +import org.bouncycastle.asn1.x509.SubjectKeyIdentifier; + +/** + * <a href="http://tools.ietf.org/html/rfc5652#section-6.2.2">RFC 5652</a>: + * Content encryption key delivery mechanisms. + * <pre> + * OriginatorIdentifierOrKey ::= CHOICE { + * issuerAndSerialNumber IssuerAndSerialNumber, + * subjectKeyIdentifier [0] SubjectKeyIdentifier, + * originatorKey [1] OriginatorPublicKey + * } + * + * SubjectKeyIdentifier ::= OCTET STRING + * </pre> + */ +public class OriginatorIdentifierOrKey + extends ASN1Object + implements ASN1Choice +{ + private ASN1Encodable id; + + public OriginatorIdentifierOrKey( + IssuerAndSerialNumber id) + { + this.id = id; + } + + /** + * @deprecated use version taking a SubjectKeyIdentifier + */ + public OriginatorIdentifierOrKey( + ASN1OctetString id) + { + this(new SubjectKeyIdentifier(id.getOctets())); + } + + public OriginatorIdentifierOrKey( + SubjectKeyIdentifier id) + { + this.id = new DERTaggedObject(false, 0, id); + } + + public OriginatorIdentifierOrKey( + OriginatorPublicKey id) + { + this.id = new DERTaggedObject(false, 1, id); + } + + /** + * @deprecated use more specific version + */ + public OriginatorIdentifierOrKey( + ASN1Primitive id) + { + this.id = id; + } + + /** + * Return an OriginatorIdentifierOrKey object from a tagged object. + * + * @param o the tagged object holding the object we want. + * @param explicit true if the object is meant to be explicitly + * tagged false otherwise. + * @exception IllegalArgumentException if the object held by the + * tagged object cannot be converted. + */ + public static OriginatorIdentifierOrKey getInstance( + ASN1TaggedObject o, + boolean explicit) + { + if (!explicit) + { + throw new IllegalArgumentException( + "Can't implicitly tag OriginatorIdentifierOrKey"); + } + + return getInstance(o.getObject()); + } + + /** + * Return an OriginatorIdentifierOrKey object from the given object. + * <p> + * Accepted inputs: + * <ul> + * <li> null → null + * <li> {@link OriginatorIdentifierOrKey} object + * <li> {@link IssuerAndSerialNumber} object + * <li> {@link SubjectKeyIdentifier} object + * <li> {@link OriginatorPublicKey} object + * <li> {@link org.bouncycastle.asn1.ASN1TaggedObject#getInstance(java.lang.Object) ASN1TaggedObject} input formats with IssuerAndSerialNumber structure inside + * </ul> + * + * @param o the object we want converted. + * @exception IllegalArgumentException if the object cannot be converted. + */ + public static OriginatorIdentifierOrKey getInstance( + Object o) + { + if (o == null || o instanceof OriginatorIdentifierOrKey) + { + return (OriginatorIdentifierOrKey)o; + } + + if (o instanceof IssuerAndSerialNumber) + { + return new OriginatorIdentifierOrKey((IssuerAndSerialNumber)o); + } + + if (o instanceof SubjectKeyIdentifier) + { + return new OriginatorIdentifierOrKey((SubjectKeyIdentifier)o); + } + + if (o instanceof OriginatorPublicKey) + { + return new OriginatorIdentifierOrKey((OriginatorPublicKey)o); + } + + if (o instanceof ASN1TaggedObject) + { + // TODO Add validation + return new OriginatorIdentifierOrKey((ASN1TaggedObject)o); + } + + throw new IllegalArgumentException("Invalid OriginatorIdentifierOrKey: " + o.getClass().getName()); + } + + public ASN1Encodable getId() + { + return id; + } + + public IssuerAndSerialNumber getIssuerAndSerialNumber() + { + if (id instanceof IssuerAndSerialNumber) + { + return (IssuerAndSerialNumber)id; + } + + return null; + } + + public SubjectKeyIdentifier getSubjectKeyIdentifier() + { + if (id instanceof ASN1TaggedObject && ((ASN1TaggedObject)id).getTagNo() == 0) + { + return SubjectKeyIdentifier.getInstance((ASN1TaggedObject)id, false); + } + + return null; + } + + public OriginatorPublicKey getOriginatorKey() + { + if (id instanceof ASN1TaggedObject && ((ASN1TaggedObject)id).getTagNo() == 1) + { + return OriginatorPublicKey.getInstance((ASN1TaggedObject)id, false); + } + + return null; + } + + /** + * Produce an object suitable for an ASN1OutputStream. + */ + public ASN1Primitive toASN1Primitive() + { + return id.toASN1Primitive(); + } +} diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/cms/OriginatorInfo.java b/bcprov/src/main/java/org/bouncycastle/asn1/cms/OriginatorInfo.java new file mode 100644 index 0000000..96abf7d --- /dev/null +++ b/bcprov/src/main/java/org/bouncycastle/asn1/cms/OriginatorInfo.java @@ -0,0 +1,159 @@ +package org.bouncycastle.asn1.cms; + +import org.bouncycastle.asn1.ASN1EncodableVector; +import org.bouncycastle.asn1.ASN1Object; +import org.bouncycastle.asn1.ASN1Primitive; +import org.bouncycastle.asn1.ASN1Sequence; +import org.bouncycastle.asn1.ASN1Set; +import org.bouncycastle.asn1.ASN1TaggedObject; +import org.bouncycastle.asn1.DERSequence; +import org.bouncycastle.asn1.DERTaggedObject; + +/** + * <a href="http://tools.ietf.org/html/rfc5652#section-6.2.1">RFC 5652</a>: OriginatorInfo object. + * <pre> + * RFC 3369: + * + * OriginatorInfo ::= SEQUENCE { + * certs [0] IMPLICIT CertificateSet OPTIONAL, + * crls [1] IMPLICIT CertificateRevocationLists OPTIONAL + * } + * CertificateRevocationLists ::= SET OF CertificateList (from X.509) + * + * RFC 3582 / 5652: + * + * OriginatorInfo ::= SEQUENCE { + * certs [0] IMPLICIT CertificateSet OPTIONAL, + * crls [1] IMPLICIT RevocationInfoChoices OPTIONAL + * } + * RevocationInfoChoices ::= SET OF RevocationInfoChoice + * RevocationInfoChoice ::= CHOICE { + * crl CertificateList, + * other [1] IMPLICIT OtherRevocationInfoFormat } + * + * OtherRevocationInfoFormat ::= SEQUENCE { + * otherRevInfoFormat OBJECT IDENTIFIER, + * otherRevInfo ANY DEFINED BY otherRevInfoFormat } + * </pre> + * <p> + * TODO: RevocationInfoChoices / RevocationInfoChoice. + * Constructor using CertificateSet, CertificationInfoChoices + */ +public class OriginatorInfo + extends ASN1Object +{ + private ASN1Set certs; + private ASN1Set crls; + + public OriginatorInfo( + ASN1Set certs, + ASN1Set crls) + { + this.certs = certs; + this.crls = crls; + } + + private OriginatorInfo( + ASN1Sequence seq) + { + switch (seq.size()) + { + case 0: // empty + break; + case 1: + ASN1TaggedObject o = (ASN1TaggedObject)seq.getObjectAt(0); + switch (o.getTagNo()) + { + case 0 : + certs = ASN1Set.getInstance(o, false); + break; + case 1 : + crls = ASN1Set.getInstance(o, false); + break; + default: + throw new IllegalArgumentException("Bad tag in OriginatorInfo: " + o.getTagNo()); + } + break; + case 2: + certs = ASN1Set.getInstance((ASN1TaggedObject)seq.getObjectAt(0), false); + crls = ASN1Set.getInstance((ASN1TaggedObject)seq.getObjectAt(1), false); + break; + default: + throw new IllegalArgumentException("OriginatorInfo too big"); + } + } + + /** + * Return an OriginatorInfo object from a tagged object. + * + * @param obj the tagged object holding the object we want. + * @param explicit true if the object is meant to be explicitly + * tagged false otherwise. + * @exception IllegalArgumentException if the object held by the + * tagged object cannot be converted. + */ + public static OriginatorInfo getInstance( + ASN1TaggedObject obj, + boolean explicit) + { + return getInstance(ASN1Sequence.getInstance(obj, explicit)); + } + + /** + * Return an OriginatorInfo object from the given object. + * <p> + * Accepted inputs: + * <ul> + * <li> null → null + * <li> {@link OriginatorInfo} object + * <li> {@link org.bouncycastle.asn1.ASN1Sequence#getInstance(java.lang.Object) ASN1Sequence} input formats with OriginatorInfo structure inside + * </ul> + * + * @param obj the object we want converted. + * @exception IllegalArgumentException if the object cannot be converted. + */ + public static OriginatorInfo getInstance( + Object obj) + { + if (obj instanceof OriginatorInfo) + { + return (OriginatorInfo)obj; + } + else if (obj != null) + { + return new OriginatorInfo(ASN1Sequence.getInstance(obj)); + } + + return null; + } + + public ASN1Set getCertificates() + { + return certs; + } + + public ASN1Set getCRLs() + { + return crls; + } + + /** + * Produce an object suitable for an ASN1OutputStream. + */ + public ASN1Primitive toASN1Primitive() + { + ASN1EncodableVector v = new ASN1EncodableVector(); + + if (certs != null) + { + v.add(new DERTaggedObject(false, 0, certs)); + } + + if (crls != null) + { + v.add(new DERTaggedObject(false, 1, crls)); + } + + return new DERSequence(v); + } +} diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/cms/OriginatorPublicKey.java b/bcprov/src/main/java/org/bouncycastle/asn1/cms/OriginatorPublicKey.java new file mode 100644 index 0000000..b9bc52f --- /dev/null +++ b/bcprov/src/main/java/org/bouncycastle/asn1/cms/OriginatorPublicKey.java @@ -0,0 +1,114 @@ +package org.bouncycastle.asn1.cms; + +import org.bouncycastle.asn1.ASN1EncodableVector; +import org.bouncycastle.asn1.ASN1Object; +import org.bouncycastle.asn1.ASN1Primitive; +import org.bouncycastle.asn1.ASN1Sequence; +import org.bouncycastle.asn1.ASN1TaggedObject; +import org.bouncycastle.asn1.DERBitString; +import org.bouncycastle.asn1.DERSequence; +import org.bouncycastle.asn1.x509.AlgorithmIdentifier; + +/** + * <a href="http://tools.ietf.org/html/rfc5652#section-6.2.2">RFC 5652</a>: + * Content encryption key delivery mechanisms. + * <p> + * <pre> + * OriginatorPublicKey ::= SEQUENCE { + * algorithm AlgorithmIdentifier, + * publicKey BIT STRING + * } + * </pre> + */ +public class OriginatorPublicKey + extends ASN1Object +{ + private AlgorithmIdentifier algorithm; + private DERBitString publicKey; + + public OriginatorPublicKey( + AlgorithmIdentifier algorithm, + byte[] publicKey) + { + this.algorithm = algorithm; + this.publicKey = new DERBitString(publicKey); + } + + /** + * @deprecated use getInstance() + */ + public OriginatorPublicKey( + ASN1Sequence seq) + { + algorithm = AlgorithmIdentifier.getInstance(seq.getObjectAt(0)); + publicKey = (DERBitString)seq.getObjectAt(1); + } + + /** + * Return an OriginatorPublicKey object from a tagged object. + * + * @param obj the tagged object holding the object we want. + * @param explicit true if the object is meant to be explicitly + * tagged false otherwise. + * @exception IllegalArgumentException if the object held by the + * tagged object cannot be converted. + */ + public static OriginatorPublicKey getInstance( + ASN1TaggedObject obj, + boolean explicit) + { + return getInstance(ASN1Sequence.getInstance(obj, explicit)); + } + + /** + * Return an OriginatorPublicKey object from the given object. + * <p> + * Accepted inputs: + * <ul> + * <li> null → null + * <li> {@link OriginatorPublicKey} object + * <li> {@link org.bouncycastle.asn1.ASN1Sequence#getInstance(java.lang.Object) ASN1Sequence} input formats with OriginatorPublicKey structure inside + * </ul> + * + * @param obj the object we want converted. + * @exception IllegalArgumentException if the object cannot be converted. + */ + public static OriginatorPublicKey getInstance( + Object obj) + { + if (obj instanceof OriginatorPublicKey) + { + return (OriginatorPublicKey)obj; + } + + if (obj != null) + { + return new OriginatorPublicKey(ASN1Sequence.getInstance(obj)); + } + + return null; + } + + public AlgorithmIdentifier getAlgorithm() + { + return algorithm; + } + + public DERBitString getPublicKey() + { + return publicKey; + } + + /** + * Produce an object suitable for an ASN1OutputStream. + */ + public ASN1Primitive toASN1Primitive() + { + ASN1EncodableVector v = new ASN1EncodableVector(); + + v.add(algorithm); + v.add(publicKey); + + return new DERSequence(v); + } +} diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/cms/OtherKeyAttribute.java b/bcprov/src/main/java/org/bouncycastle/asn1/cms/OtherKeyAttribute.java new file mode 100644 index 0000000..7363c81 --- /dev/null +++ b/bcprov/src/main/java/org/bouncycastle/asn1/cms/OtherKeyAttribute.java @@ -0,0 +1,96 @@ +package org.bouncycastle.asn1.cms; + +import org.bouncycastle.asn1.ASN1Encodable; +import org.bouncycastle.asn1.ASN1EncodableVector; +import org.bouncycastle.asn1.ASN1Object; +import org.bouncycastle.asn1.ASN1ObjectIdentifier; +import org.bouncycastle.asn1.ASN1Primitive; +import org.bouncycastle.asn1.ASN1Sequence; +import org.bouncycastle.asn1.DERSequence; + +/** + * <a href="http://tools.ietf.org/html/rfc5652#section-10.2.7">RFC 5652</a>: OtherKeyAttribute object. + * <p> + * <pre> + * OtherKeyAttribute ::= SEQUENCE { + * keyAttrId OBJECT IDENTIFIER, + * keyAttr ANY DEFINED BY keyAttrId OPTIONAL + * } + * </pre> + */ +public class OtherKeyAttribute + extends ASN1Object +{ + private ASN1ObjectIdentifier keyAttrId; + private ASN1Encodable keyAttr; + + /** + * Return an OtherKeyAttribute object from the given object. + * <p> + * Accepted inputs: + * <ul> + * <li> null → null + * <li> {@link OtherKeyAttribute} object + * <li> {@link org.bouncycastle.asn1.ASN1Sequence#getInstance(java.lang.Object) ASN1Sequence} input formats with OtherKeyAttribute structure inside + * </ul> + * + * @param o the object we want converted. + * @exception IllegalArgumentException if the object cannot be converted. + */ + public static OtherKeyAttribute getInstance( + Object o) + { + if (o instanceof OtherKeyAttribute) + { + return (OtherKeyAttribute)o; + } + + if (o != null) + { + return new OtherKeyAttribute(ASN1Sequence.getInstance(o)); + } + + return null; + } + + /** + * @deprecated use getInstance() + */ + public OtherKeyAttribute( + ASN1Sequence seq) + { + keyAttrId = (ASN1ObjectIdentifier)seq.getObjectAt(0); + keyAttr = seq.getObjectAt(1); + } + + public OtherKeyAttribute( + ASN1ObjectIdentifier keyAttrId, + ASN1Encodable keyAttr) + { + this.keyAttrId = keyAttrId; + this.keyAttr = keyAttr; + } + + public ASN1ObjectIdentifier getKeyAttrId() + { + return keyAttrId; + } + + public ASN1Encodable getKeyAttr() + { + return keyAttr; + } + + /** + * Produce an object suitable for an ASN1OutputStream. + */ + public ASN1Primitive toASN1Primitive() + { + ASN1EncodableVector v = new ASN1EncodableVector(); + + v.add(keyAttrId); + v.add(keyAttr); + + return new DERSequence(v); + } +} diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/cms/OtherRecipientInfo.java b/bcprov/src/main/java/org/bouncycastle/asn1/cms/OtherRecipientInfo.java new file mode 100644 index 0000000..b77b150 --- /dev/null +++ b/bcprov/src/main/java/org/bouncycastle/asn1/cms/OtherRecipientInfo.java @@ -0,0 +1,112 @@ +package org.bouncycastle.asn1.cms; + +import org.bouncycastle.asn1.ASN1Encodable; +import org.bouncycastle.asn1.ASN1EncodableVector; +import org.bouncycastle.asn1.ASN1Object; +import org.bouncycastle.asn1.ASN1ObjectIdentifier; +import org.bouncycastle.asn1.ASN1Primitive; +import org.bouncycastle.asn1.ASN1Sequence; +import org.bouncycastle.asn1.ASN1TaggedObject; +import org.bouncycastle.asn1.DERSequence; + +/** + * <a href="http://tools.ietf.org/html/rfc5652#section-6.2.5">RFC 5652</a>: + * Content encryption key delivery mechanisms. + * <pre> + * OtherRecipientInfo ::= SEQUENCE { + * oriType OBJECT IDENTIFIER, + * oriValue ANY DEFINED BY oriType } + * </pre> + */ +public class OtherRecipientInfo + extends ASN1Object +{ + private ASN1ObjectIdentifier oriType; + private ASN1Encodable oriValue; + + public OtherRecipientInfo( + ASN1ObjectIdentifier oriType, + ASN1Encodable oriValue) + { + this.oriType = oriType; + this.oriValue = oriValue; + } + + /** + * @deprecated use getInstance(). + */ + public OtherRecipientInfo( + ASN1Sequence seq) + { + oriType = ASN1ObjectIdentifier.getInstance(seq.getObjectAt(0)); + oriValue = seq.getObjectAt(1); + } + + /** + * Return a OtherRecipientInfo object from a tagged object. + * + * @param obj the tagged object holding the object we want. + * @param explicit true if the object is meant to be explicitly + * tagged false otherwise. + * @exception IllegalArgumentException if the object held by the + * tagged object cannot be converted. + */ + public static OtherRecipientInfo getInstance( + ASN1TaggedObject obj, + boolean explicit) + { + return getInstance(ASN1Sequence.getInstance(obj, explicit)); + } + + /** + * Return a OtherRecipientInfo object from the given object. + * <p> + * Accepted inputs: + * <ul> + * <li> null → null + * <li> {@link PasswordRecipientInfo} object + * <li> {@link org.bouncycastle.asn1.ASN1Sequence#getInstance(java.lang.Object) ASN1Sequence} input formats with OtherRecipientInfo structure inside + * </ul> + * + * @param obj the object we want converted. + * @exception IllegalArgumentException if the object cannot be converted. + */ + public static OtherRecipientInfo getInstance( + Object obj) + { + if (obj instanceof OtherRecipientInfo) + { + return (OtherRecipientInfo)obj; + } + + if (obj != null) + { + return new OtherRecipientInfo(ASN1Sequence.getInstance(obj)); + } + + return null; + } + + public ASN1ObjectIdentifier getType() + { + return oriType; + } + + public ASN1Encodable getValue() + { + return oriValue; + } + + /** + * Produce an object suitable for an ASN1OutputStream. + */ + public ASN1Primitive toASN1Primitive() + { + ASN1EncodableVector v = new ASN1EncodableVector(); + + v.add(oriType); + v.add(oriValue); + + return new DERSequence(v); + } +} diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/cms/OtherRevocationInfoFormat.java b/bcprov/src/main/java/org/bouncycastle/asn1/cms/OtherRevocationInfoFormat.java new file mode 100644 index 0000000..a8348ff --- /dev/null +++ b/bcprov/src/main/java/org/bouncycastle/asn1/cms/OtherRevocationInfoFormat.java @@ -0,0 +1,109 @@ +package org.bouncycastle.asn1.cms; + +import org.bouncycastle.asn1.ASN1Encodable; +import org.bouncycastle.asn1.ASN1EncodableVector; +import org.bouncycastle.asn1.ASN1Object; +import org.bouncycastle.asn1.ASN1ObjectIdentifier; +import org.bouncycastle.asn1.ASN1Primitive; +import org.bouncycastle.asn1.ASN1Sequence; +import org.bouncycastle.asn1.ASN1TaggedObject; +import org.bouncycastle.asn1.DERSequence; + +/** + * <a href="http://tools.ietf.org/html/rfc5652#section-10.2.1">RFC 5652</a>: OtherRevocationInfoFormat object. + * <p> + * <pre> + * OtherRevocationInfoFormat ::= SEQUENCE { + * otherRevInfoFormat OBJECT IDENTIFIER, + * otherRevInfo ANY DEFINED BY otherRevInfoFormat } + * </pre> + */ +public class OtherRevocationInfoFormat + extends ASN1Object +{ + private ASN1ObjectIdentifier otherRevInfoFormat; + private ASN1Encodable otherRevInfo; + + public OtherRevocationInfoFormat( + ASN1ObjectIdentifier otherRevInfoFormat, + ASN1Encodable otherRevInfo) + { + this.otherRevInfoFormat = otherRevInfoFormat; + this.otherRevInfo = otherRevInfo; + } + + private OtherRevocationInfoFormat( + ASN1Sequence seq) + { + otherRevInfoFormat = ASN1ObjectIdentifier.getInstance(seq.getObjectAt(0)); + otherRevInfo = seq.getObjectAt(1); + } + + /** + * Return a OtherRevocationInfoFormat object from a tagged object. + * + * @param obj the tagged object holding the object we want. + * @param explicit true if the object is meant to be explicitly + * tagged false otherwise. + * @exception IllegalArgumentException if the object held by the + * tagged object cannot be converted. + */ + public static OtherRevocationInfoFormat getInstance( + ASN1TaggedObject obj, + boolean explicit) + { + return getInstance(ASN1Sequence.getInstance(obj, explicit)); + } + + /** + * Return a OtherRevocationInfoFormat object from the given object. + * <p> + * Accepted inputs: + * <ul> + * <li> null → null + * <li> {@link OtherRevocationInfoFormat} object + * <li> {@link org.bouncycastle.asn1.ASN1Sequence#getInstance(java.lang.Object) ASN1Sequence} input formats with OtherRevocationInfoFormat structure inside + * </ul> + * + * @param obj the object we want converted. + * @exception IllegalArgumentException if the object cannot be converted. + */ + public static OtherRevocationInfoFormat getInstance( + Object obj) + { + if (obj instanceof OtherRevocationInfoFormat) + { + return (OtherRevocationInfoFormat)obj; + } + + if (obj != null) + { + return new OtherRevocationInfoFormat(ASN1Sequence.getInstance(obj)); + } + + return null; + } + + public ASN1ObjectIdentifier getInfoFormat() + { + return otherRevInfoFormat; + } + + public ASN1Encodable getInfo() + { + return otherRevInfo; + } + + /** + * Produce an object suitable for an ASN1OutputStream. + */ + public ASN1Primitive toASN1Primitive() + { + ASN1EncodableVector v = new ASN1EncodableVector(); + + v.add(otherRevInfoFormat); + v.add(otherRevInfo); + + return new DERSequence(v); + } +} diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/cms/PasswordRecipientInfo.java b/bcprov/src/main/java/org/bouncycastle/asn1/cms/PasswordRecipientInfo.java new file mode 100644 index 0000000..7ed16cf --- /dev/null +++ b/bcprov/src/main/java/org/bouncycastle/asn1/cms/PasswordRecipientInfo.java @@ -0,0 +1,157 @@ +package org.bouncycastle.asn1.cms; + +import org.bouncycastle.asn1.ASN1EncodableVector; +import org.bouncycastle.asn1.ASN1Integer; +import org.bouncycastle.asn1.ASN1Object; +import org.bouncycastle.asn1.ASN1OctetString; +import org.bouncycastle.asn1.ASN1Primitive; +import org.bouncycastle.asn1.ASN1Sequence; +import org.bouncycastle.asn1.ASN1TaggedObject; +import org.bouncycastle.asn1.DERSequence; +import org.bouncycastle.asn1.DERTaggedObject; +import org.bouncycastle.asn1.x509.AlgorithmIdentifier; + +/** + * <a href="http://tools.ietf.org/html/rfc5652#section-10.2.7">RFC 5652</a>: + * Content encryption key delivery mechanisms. + * <pre> + * PasswordRecipientInfo ::= SEQUENCE { + * version CMSVersion, -- Always set to 0 + * keyDerivationAlgorithm [0] KeyDerivationAlgorithmIdentifier + * OPTIONAL, + * keyEncryptionAlgorithm KeyEncryptionAlgorithmIdentifier, + * encryptedKey EncryptedKey } + * </pre> + */ +public class PasswordRecipientInfo + extends ASN1Object +{ + private ASN1Integer version; + private AlgorithmIdentifier keyDerivationAlgorithm; + private AlgorithmIdentifier keyEncryptionAlgorithm; + private ASN1OctetString encryptedKey; + + public PasswordRecipientInfo( + AlgorithmIdentifier keyEncryptionAlgorithm, + ASN1OctetString encryptedKey) + { + this.version = new ASN1Integer(0); + this.keyEncryptionAlgorithm = keyEncryptionAlgorithm; + this.encryptedKey = encryptedKey; + } + + public PasswordRecipientInfo( + AlgorithmIdentifier keyDerivationAlgorithm, + AlgorithmIdentifier keyEncryptionAlgorithm, + ASN1OctetString encryptedKey) + { + this.version = new ASN1Integer(0); + this.keyDerivationAlgorithm = keyDerivationAlgorithm; + this.keyEncryptionAlgorithm = keyEncryptionAlgorithm; + this.encryptedKey = encryptedKey; + } + + /** + * @deprecated use getInstance() method. + */ + public PasswordRecipientInfo( + ASN1Sequence seq) + { + version = (ASN1Integer)seq.getObjectAt(0); + if (seq.getObjectAt(1) instanceof ASN1TaggedObject) + { + keyDerivationAlgorithm = AlgorithmIdentifier.getInstance((ASN1TaggedObject)seq.getObjectAt(1), false); + keyEncryptionAlgorithm = AlgorithmIdentifier.getInstance(seq.getObjectAt(2)); + encryptedKey = (ASN1OctetString)seq.getObjectAt(3); + } + else + { + keyEncryptionAlgorithm = AlgorithmIdentifier.getInstance(seq.getObjectAt(1)); + encryptedKey = (ASN1OctetString)seq.getObjectAt(2); + } + } + + /** + * Return a PasswordRecipientInfo object from a tagged object. + * + * @param obj the tagged object holding the object we want. + * @param explicit true if the object is meant to be explicitly + * tagged false otherwise. + * @exception IllegalArgumentException if the object held by the + * tagged object cannot be converted. + */ + public static PasswordRecipientInfo getInstance( + ASN1TaggedObject obj, + boolean explicit) + { + return getInstance(ASN1Sequence.getInstance(obj, explicit)); + } + + /** + * Return a PasswordRecipientInfo object from the given object. + * <p> + * Accepted inputs: + * <ul> + * <li> null → null + * <li> {@link PasswordRecipientInfo} object + * <li> {@link org.bouncycastle.asn1.ASN1Sequence#getInstance(java.lang.Object) ASN1Sequence} input formats with PasswordRecipientInfo structure inside + * </ul> + * + * @param obj the object we want converted. + * @exception IllegalArgumentException if the object cannot be converted. + */ + public static PasswordRecipientInfo getInstance( + Object obj) + { + if (obj instanceof PasswordRecipientInfo) + { + return (PasswordRecipientInfo)obj; + } + + if (obj != null) + { + return new PasswordRecipientInfo(ASN1Sequence.getInstance(obj)); + } + + return null; + } + + public ASN1Integer getVersion() + { + return version; + } + + public AlgorithmIdentifier getKeyDerivationAlgorithm() + { + return keyDerivationAlgorithm; + } + + public AlgorithmIdentifier getKeyEncryptionAlgorithm() + { + return keyEncryptionAlgorithm; + } + + public ASN1OctetString getEncryptedKey() + { + return encryptedKey; + } + + /** + * Produce an object suitable for an ASN1OutputStream. + */ + public ASN1Primitive toASN1Primitive() + { + ASN1EncodableVector v = new ASN1EncodableVector(); + + v.add(version); + + if (keyDerivationAlgorithm != null) + { + v.add(new DERTaggedObject(false, 0, keyDerivationAlgorithm)); + } + v.add(keyEncryptionAlgorithm); + v.add(encryptedKey); + + return new DERSequence(v); + } +} diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/cms/RecipientEncryptedKey.java b/bcprov/src/main/java/org/bouncycastle/asn1/cms/RecipientEncryptedKey.java new file mode 100644 index 0000000..5062c10 --- /dev/null +++ b/bcprov/src/main/java/org/bouncycastle/asn1/cms/RecipientEncryptedKey.java @@ -0,0 +1,109 @@ +package org.bouncycastle.asn1.cms; + +import org.bouncycastle.asn1.ASN1EncodableVector; +import org.bouncycastle.asn1.ASN1Object; +import org.bouncycastle.asn1.ASN1OctetString; +import org.bouncycastle.asn1.ASN1Primitive; +import org.bouncycastle.asn1.ASN1Sequence; +import org.bouncycastle.asn1.ASN1TaggedObject; +import org.bouncycastle.asn1.DERSequence; + +/** + * <a href="http://tools.ietf.org/html/rfc5652#section-6.2.2">RFC 5652</a>: + * Content encryption key delivery mechanisms. + * <pre> + * RecipientEncryptedKey ::= SEQUENCE { + * rid KeyAgreeRecipientIdentifier, + * encryptedKey EncryptedKey + * } + * </pre> + */ +public class RecipientEncryptedKey + extends ASN1Object +{ + private KeyAgreeRecipientIdentifier identifier; + private ASN1OctetString encryptedKey; + + private RecipientEncryptedKey( + ASN1Sequence seq) + { + identifier = KeyAgreeRecipientIdentifier.getInstance(seq.getObjectAt(0)); + encryptedKey = (ASN1OctetString)seq.getObjectAt(1); + } + + /** + * Return an RecipientEncryptedKey object from a tagged object. + * + * @param obj the tagged object holding the object we want. + * @param explicit true if the object is meant to be explicitly + * tagged false otherwise. + * @exception IllegalArgumentException if the object held by the + * tagged object cannot be converted. + */ + public static RecipientEncryptedKey getInstance( + ASN1TaggedObject obj, + boolean explicit) + { + return getInstance(ASN1Sequence.getInstance(obj, explicit)); + } + + /** + * Return a RecipientEncryptedKey object from the given object. + * <p> + * Accepted inputs: + * <ul> + * <li> null → null + * <li> {@link RecipientEncryptedKey} object + * <li> {@link org.bouncycastle.asn1.ASN1Sequence#getInstance(java.lang.Object) ASN1Sequence} input formats with RecipientEncryptedKey structure inside + * </ul> + * + * @param obj the object we want converted. + * @exception IllegalArgumentException if the object cannot be converted. + */ + public static RecipientEncryptedKey getInstance( + Object obj) + { + if (obj instanceof RecipientEncryptedKey) + { + return (RecipientEncryptedKey)obj; + } + + if (obj != null) + { + return new RecipientEncryptedKey(ASN1Sequence.getInstance(obj)); + } + + return null; + } + + public RecipientEncryptedKey( + KeyAgreeRecipientIdentifier id, + ASN1OctetString encryptedKey) + { + this.identifier = id; + this.encryptedKey = encryptedKey; + } + + public KeyAgreeRecipientIdentifier getIdentifier() + { + return identifier; + } + + public ASN1OctetString getEncryptedKey() + { + return encryptedKey; + } + + /** + * Produce an object suitable for an ASN1OutputStream. + */ + public ASN1Primitive toASN1Primitive() + { + ASN1EncodableVector v = new ASN1EncodableVector(); + + v.add(identifier); + v.add(encryptedKey); + + return new DERSequence(v); + } +} diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/cms/RecipientIdentifier.java b/bcprov/src/main/java/org/bouncycastle/asn1/cms/RecipientIdentifier.java new file mode 100644 index 0000000..66b154a --- /dev/null +++ b/bcprov/src/main/java/org/bouncycastle/asn1/cms/RecipientIdentifier.java @@ -0,0 +1,111 @@ +package org.bouncycastle.asn1.cms; + +import org.bouncycastle.asn1.ASN1Choice; +import org.bouncycastle.asn1.ASN1Encodable; +import org.bouncycastle.asn1.ASN1Object; +import org.bouncycastle.asn1.ASN1OctetString; +import org.bouncycastle.asn1.ASN1Primitive; +import org.bouncycastle.asn1.ASN1TaggedObject; +import org.bouncycastle.asn1.DERTaggedObject; + +/** + * <a href="http://tools.ietf.org/html/rfc5652#section-6.2.1">RFC 5652</a>: + * Content encryption key delivery mechanisms. + * <pre> + * RecipientIdentifier ::= CHOICE { + * issuerAndSerialNumber IssuerAndSerialNumber, + * subjectKeyIdentifier [0] SubjectKeyIdentifier + * } + * + * SubjectKeyIdentifier ::= OCTET STRING + * </pre> + */ +public class RecipientIdentifier + extends ASN1Object + implements ASN1Choice +{ + private ASN1Encodable id; + + public RecipientIdentifier( + IssuerAndSerialNumber id) + { + this.id = id; + } + + public RecipientIdentifier( + ASN1OctetString id) + { + this.id = new DERTaggedObject(false, 0, id); + } + + public RecipientIdentifier( + ASN1Primitive id) + { + this.id = id; + } + + /** + * Return a RecipientIdentifier object from the given object. + * <p> + * Accepted inputs: + * <ul> + * <li> null → null + * <li> {@link RecipientIdentifier} object + * <li> {@link IssuerAndSerialNumber} object + * <li> {@link org.bouncycastle.asn1.ASN1OctetString#getInstance(java.lang.Object) ASN1OctetString} input formats (OctetString, byte[]) with value of KeyIdentifier in DER form + * <li> {@link org.bouncycastle.asn1.ASN1Primitive ASN1Primitive} for RecipientIdentifier constructor + * </ul> + * + * @param o the object we want converted. + * @exception IllegalArgumentException if the object cannot be converted. + */ + public static RecipientIdentifier getInstance( + Object o) + { + if (o == null || o instanceof RecipientIdentifier) + { + return (RecipientIdentifier)o; + } + + if (o instanceof IssuerAndSerialNumber) + { + return new RecipientIdentifier((IssuerAndSerialNumber)o); + } + + if (o instanceof ASN1OctetString) + { + return new RecipientIdentifier((ASN1OctetString)o); + } + + if (o instanceof ASN1Primitive) + { + return new RecipientIdentifier((ASN1Primitive)o); + } + + throw new IllegalArgumentException( + "Illegal object in RecipientIdentifier: " + o.getClass().getName()); + } + + public boolean isTagged() + { + return (id instanceof ASN1TaggedObject); + } + + public ASN1Encodable getId() + { + if (id instanceof ASN1TaggedObject) + { + return ASN1OctetString.getInstance((ASN1TaggedObject)id, false); + } + + return IssuerAndSerialNumber.getInstance(id); + } + + /** + * Produce an object suitable for an ASN1OutputStream. + */ + public ASN1Primitive toASN1Primitive() + { + return id.toASN1Primitive(); + } +} diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/cms/RecipientInfo.java b/bcprov/src/main/java/org/bouncycastle/asn1/cms/RecipientInfo.java new file mode 100644 index 0000000..39a7bb2 --- /dev/null +++ b/bcprov/src/main/java/org/bouncycastle/asn1/cms/RecipientInfo.java @@ -0,0 +1,173 @@ +package org.bouncycastle.asn1.cms; + +import org.bouncycastle.asn1.ASN1Choice; +import org.bouncycastle.asn1.ASN1Encodable; +import org.bouncycastle.asn1.ASN1Integer; +import org.bouncycastle.asn1.ASN1Object; +import org.bouncycastle.asn1.ASN1Primitive; +import org.bouncycastle.asn1.ASN1Sequence; +import org.bouncycastle.asn1.ASN1TaggedObject; +import org.bouncycastle.asn1.DERTaggedObject; + +/** + * <a href="http://tools.ietf.org/html/rfc5652#section-6.2">RFC 5652</a>: + * Content encryption key delivery mechanisms. + * <p> + * <pre> + * RecipientInfo ::= CHOICE { + * ktri KeyTransRecipientInfo, + * kari [1] KeyAgreeRecipientInfo, + * kekri [2] KEKRecipientInfo, + * pwri [3] PasswordRecipientInfo, + * ori [4] OtherRecipientInfo } + * </pre> + */ +public class RecipientInfo + extends ASN1Object + implements ASN1Choice +{ + ASN1Encodable info; + + public RecipientInfo( + KeyTransRecipientInfo info) + { + this.info = info; + } + + public RecipientInfo( + KeyAgreeRecipientInfo info) + { + this.info = new DERTaggedObject(false, 1, info); + } + + public RecipientInfo( + KEKRecipientInfo info) + { + this.info = new DERTaggedObject(false, 2, info); + } + + public RecipientInfo( + PasswordRecipientInfo info) + { + this.info = new DERTaggedObject(false, 3, info); + } + + public RecipientInfo( + OtherRecipientInfo info) + { + this.info = new DERTaggedObject(false, 4, info); + } + + public RecipientInfo( + ASN1Primitive info) + { + this.info = info; + } + + /** + * Return a RecipientInfo object from the given object. + * <p> + * Accepted inputs: + * <ul> + * <li> null → null + * <li> {@link RecipientInfo} object + * <li> {@link org.bouncycastle.asn1.ASN1Sequence#getInstance(java.lang.Object) ASN1Sequence} input formats with RecipientInfo structure inside + * <li> {@link org.bouncycastle.asn1.ASN1TaggedObject#getInstance(java.lang.Object) ASN1TaggedObject} input formats with RecipientInfo structure inside + * </ul> + * + * @param o the object we want converted. + * @exception IllegalArgumentException if the object cannot be converted. + */ + public static RecipientInfo getInstance( + Object o) + { + if (o == null || o instanceof RecipientInfo) + { + return (RecipientInfo)o; + } + else if (o instanceof ASN1Sequence) + { + return new RecipientInfo((ASN1Sequence)o); + } + else if (o instanceof ASN1TaggedObject) + { + return new RecipientInfo((ASN1TaggedObject)o); + } + + throw new IllegalArgumentException("unknown object in factory: " + + o.getClass().getName()); + } + + public ASN1Integer getVersion() + { + if (info instanceof ASN1TaggedObject) + { + ASN1TaggedObject o = (ASN1TaggedObject)info; + + switch (o.getTagNo()) + { + case 1: + return KeyAgreeRecipientInfo.getInstance(o, false).getVersion(); + case 2: + return getKEKInfo(o).getVersion(); + case 3: + return PasswordRecipientInfo.getInstance(o, false).getVersion(); + case 4: + return new ASN1Integer(0); // no syntax version for OtherRecipientInfo + default: + throw new IllegalStateException("unknown tag"); + } + } + + return KeyTransRecipientInfo.getInstance(info).getVersion(); + } + + public boolean isTagged() + { + return (info instanceof ASN1TaggedObject); + } + + public ASN1Encodable getInfo() + { + if (info instanceof ASN1TaggedObject) + { + ASN1TaggedObject o = (ASN1TaggedObject)info; + + switch (o.getTagNo()) + { + case 1: + return KeyAgreeRecipientInfo.getInstance(o, false); + case 2: + return getKEKInfo(o); + case 3: + return PasswordRecipientInfo.getInstance(o, false); + case 4: + return OtherRecipientInfo.getInstance(o, false); + default: + throw new IllegalStateException("unknown tag"); + } + } + + return KeyTransRecipientInfo.getInstance(info); + } + + private KEKRecipientInfo getKEKInfo(ASN1TaggedObject o) + { + if (o.isExplicit()) + { // compatibilty with erroneous version + return KEKRecipientInfo.getInstance(o, true); + } + else + { + return KEKRecipientInfo.getInstance(o, false); + } + } + + /** + * Produce an object suitable for an ASN1OutputStream. + */ + public ASN1Primitive toASN1Primitive() + { + return info.toASN1Primitive(); + } +} diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/cms/RecipientKeyIdentifier.java b/bcprov/src/main/java/org/bouncycastle/asn1/cms/RecipientKeyIdentifier.java new file mode 100644 index 0000000..a680e4a --- /dev/null +++ b/bcprov/src/main/java/org/bouncycastle/asn1/cms/RecipientKeyIdentifier.java @@ -0,0 +1,171 @@ +package org.bouncycastle.asn1.cms; + +import org.bouncycastle.asn1.ASN1EncodableVector; +import org.bouncycastle.asn1.ASN1GeneralizedTime; +import org.bouncycastle.asn1.ASN1Object; +import org.bouncycastle.asn1.ASN1OctetString; +import org.bouncycastle.asn1.ASN1Primitive; +import org.bouncycastle.asn1.ASN1Sequence; +import org.bouncycastle.asn1.ASN1TaggedObject; +import org.bouncycastle.asn1.DEROctetString; +import org.bouncycastle.asn1.DERSequence; + +/** + * <a href="http://tools.ietf.org/html/rfc5652#section-6.2.2">RFC 5652</a>: + * Content encryption key delivery mechanisms. + * <p> + * <pre> + * RecipientKeyIdentifier ::= SEQUENCE { + * subjectKeyIdentifier SubjectKeyIdentifier, + * date GeneralizedTime OPTIONAL, + * other OtherKeyAttribute OPTIONAL + * } + * + * SubjectKeyIdentifier ::= OCTET STRING + * </pre> + */ +public class RecipientKeyIdentifier + extends ASN1Object +{ + private ASN1OctetString subjectKeyIdentifier; + private ASN1GeneralizedTime date; + private OtherKeyAttribute other; + + public RecipientKeyIdentifier( + ASN1OctetString subjectKeyIdentifier, + ASN1GeneralizedTime date, + OtherKeyAttribute other) + { + this.subjectKeyIdentifier = subjectKeyIdentifier; + this.date = date; + this.other = other; + } + + public RecipientKeyIdentifier( + byte[] subjectKeyIdentifier, + ASN1GeneralizedTime date, + OtherKeyAttribute other) + { + this.subjectKeyIdentifier = new DEROctetString(subjectKeyIdentifier); + this.date = date; + this.other = other; + } + + public RecipientKeyIdentifier( + byte[] subjectKeyIdentifier) + { + this(subjectKeyIdentifier, null, null); + } + + /** + * @deprecated use getInstance() + */ + public RecipientKeyIdentifier( + ASN1Sequence seq) + { + subjectKeyIdentifier = ASN1OctetString.getInstance( + seq.getObjectAt(0)); + + switch(seq.size()) + { + case 1: + break; + case 2: + if (seq.getObjectAt(1) instanceof ASN1GeneralizedTime) + { + date = ASN1GeneralizedTime.getInstance(seq.getObjectAt(1)); + } + else + { + other = OtherKeyAttribute.getInstance(seq.getObjectAt(2)); + } + break; + case 3: + date = ASN1GeneralizedTime.getInstance(seq.getObjectAt(1)); + other = OtherKeyAttribute.getInstance(seq.getObjectAt(2)); + break; + default: + throw new IllegalArgumentException("Invalid RecipientKeyIdentifier"); + } + } + + /** + * Return a RecipientKeyIdentifier object from a tagged object. + * + * @param ato the tagged object holding the object we want. + * @param isExplicit true if the object is meant to be explicitly + * tagged false otherwise. + * @exception IllegalArgumentException if the object held by the + * tagged object cannot be converted. + */ + public static RecipientKeyIdentifier getInstance(ASN1TaggedObject ato, boolean isExplicit) + { + return getInstance(ASN1Sequence.getInstance(ato, isExplicit)); + } + + /** + * Return a RecipientKeyIdentifier object from the given object. + * <p> + * Accepted inputs: + * <ul> + * <li> null → null + * <li> {@link RecipientKeyIdentifier} object + * <li> {@link org.bouncycastle.asn1.ASN1Sequence#getInstance(java.lang.Object) ASN1Sequence} input formats with RecipientKeyIdentifier structure inside + * </ul> + * + * @param obj the object we want converted. + * @exception IllegalArgumentException if the object cannot be converted. + */ + public static RecipientKeyIdentifier getInstance(Object obj) + { + if (obj instanceof RecipientKeyIdentifier) + { + return (RecipientKeyIdentifier)obj; + } + + if(obj != null) + { + return new RecipientKeyIdentifier(ASN1Sequence.getInstance(obj)); + } + + return null; + } + + public ASN1OctetString getSubjectKeyIdentifier() + { + return subjectKeyIdentifier; + } + + public ASN1GeneralizedTime getDate() + { + return date; + } + + public OtherKeyAttribute getOtherKeyAttribute() + { + return other; + } + + + /** + * Produce an object suitable for an ASN1OutputStream. + */ + public ASN1Primitive toASN1Primitive() + { + ASN1EncodableVector v = new ASN1EncodableVector(); + + v.add(subjectKeyIdentifier); + + if (date != null) + { + v.add(date); + } + + if (other != null) + { + v.add(other); + } + + return new DERSequence(v); + } +} diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/cms/SCVPReqRes.java b/bcprov/src/main/java/org/bouncycastle/asn1/cms/SCVPReqRes.java new file mode 100644 index 0000000..52279c3 --- /dev/null +++ b/bcprov/src/main/java/org/bouncycastle/asn1/cms/SCVPReqRes.java @@ -0,0 +1,108 @@ +package org.bouncycastle.asn1.cms; + +import org.bouncycastle.asn1.ASN1EncodableVector; +import org.bouncycastle.asn1.ASN1Object; +import org.bouncycastle.asn1.ASN1Primitive; +import org.bouncycastle.asn1.ASN1Sequence; +import org.bouncycastle.asn1.ASN1TaggedObject; +import org.bouncycastle.asn1.DERSequence; +import org.bouncycastle.asn1.DERTaggedObject; + +/** + * <a href="http://tools.ietf.org/html/rfc5940">RFC 5940</a>: + * Additional Cryptographic Message Syntax (CMS) Revocation Information Choices. + * <p> + * <pre> + * SCVPReqRes ::= SEQUENCE { + * request [0] EXPLICIT ContentInfo OPTIONAL, + * response ContentInfo } + * </pre> + */ +public class SCVPReqRes + extends ASN1Object +{ + private final ContentInfo request; + private final ContentInfo response; + + /** + * Return a SCVPReqRes object from the given object. + * <p> + * Accepted inputs: + * <ul> + * <li> null → null + * <li> {@link SCVPReqRes} object + * <li> {@link org.bouncycastle.asn1.ASN1Sequence#getInstance(java.lang.Object) ASN1Sequence} input formats with SCVPReqRes structure inside + * </ul> + * + * @param obj the object we want converted. + * @exception IllegalArgumentException if the object cannot be converted. + */ + public static SCVPReqRes getInstance( + Object obj) + { + if (obj instanceof SCVPReqRes) + { + return (SCVPReqRes)obj; + } + else if (obj != null) + { + return new SCVPReqRes(ASN1Sequence.getInstance(obj)); + } + + return null; + } + + private SCVPReqRes( + ASN1Sequence seq) + { + if (seq.getObjectAt(0) instanceof ASN1TaggedObject) + { + this.request = ContentInfo.getInstance(ASN1TaggedObject.getInstance(seq.getObjectAt(0)), true); + this.response = ContentInfo.getInstance(seq.getObjectAt(1)); + } + else + { + this.request = null; + this.response = ContentInfo.getInstance(seq.getObjectAt(0)); + } + } + + public SCVPReqRes(ContentInfo response) + { + this.request = null; // use of this confuses earlier JDKs + this.response = response; + } + + public SCVPReqRes(ContentInfo request, ContentInfo response) + { + this.request = request; + this.response = response; + } + + public ContentInfo getRequest() + { + return request; + } + + public ContentInfo getResponse() + { + return response; + } + + /** + * @return the ASN.1 primitive representation. + */ + public ASN1Primitive toASN1Primitive() + { + ASN1EncodableVector v = new ASN1EncodableVector(); + + if (request != null) + { + v.add(new DERTaggedObject(true, 0, request)); + } + + v.add(response); + + return new DERSequence(v); + } +} diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/cms/SignedDataParser.java b/bcprov/src/main/java/org/bouncycastle/asn1/cms/SignedDataParser.java new file mode 100644 index 0000000..df22b8e --- /dev/null +++ b/bcprov/src/main/java/org/bouncycastle/asn1/cms/SignedDataParser.java @@ -0,0 +1,141 @@ +package org.bouncycastle.asn1.cms; + +import java.io.IOException; + +import org.bouncycastle.asn1.ASN1Integer; +import org.bouncycastle.asn1.ASN1Sequence; +import org.bouncycastle.asn1.ASN1SequenceParser; +import org.bouncycastle.asn1.ASN1Set; +import org.bouncycastle.asn1.ASN1SetParser; +import org.bouncycastle.asn1.ASN1TaggedObjectParser; +import org.bouncycastle.asn1.BERTags; + +/** + * Parser for <a href="http://tools.ietf.org/html/rfc5652#section-5.1">RFC 5652</a>: {@link SignedData} object. + * <p> + * <pre> + * SignedData ::= SEQUENCE { + * version CMSVersion, + * digestAlgorithms DigestAlgorithmIdentifiers, + * encapContentInfo EncapsulatedContentInfo, + * certificates [0] IMPLICIT CertificateSet OPTIONAL, + * crls [1] IMPLICIT CertificateRevocationLists OPTIONAL, + * signerInfos SignerInfos + * } + * </pre> + */ +public class SignedDataParser +{ + private ASN1SequenceParser _seq; + private ASN1Integer _version; + private Object _nextObject; + private boolean _certsCalled; + private boolean _crlsCalled; + + public static SignedDataParser getInstance( + Object o) + throws IOException + { + if (o instanceof ASN1Sequence) + { + return new SignedDataParser(((ASN1Sequence)o).parser()); + } + if (o instanceof ASN1SequenceParser) + { + return new SignedDataParser((ASN1SequenceParser)o); + } + + throw new IOException("unknown object encountered: " + o.getClass().getName()); + } + + private SignedDataParser( + ASN1SequenceParser seq) + throws IOException + { + this._seq = seq; + this._version = (ASN1Integer)seq.readObject(); + } + + public ASN1Integer getVersion() + { + return _version; + } + + public ASN1SetParser getDigestAlgorithms() + throws IOException + { + Object o = _seq.readObject(); + + if (o instanceof ASN1Set) + { + return ((ASN1Set)o).parser(); + } + + return (ASN1SetParser)o; + } + + public ContentInfoParser getEncapContentInfo() + throws IOException + { + return new ContentInfoParser((ASN1SequenceParser)_seq.readObject()); + } + + public ASN1SetParser getCertificates() + throws IOException + { + _certsCalled = true; + _nextObject = _seq.readObject(); + + if (_nextObject instanceof ASN1TaggedObjectParser && ((ASN1TaggedObjectParser)_nextObject).getTagNo() == 0) + { + ASN1SetParser certs = (ASN1SetParser)((ASN1TaggedObjectParser)_nextObject).getObjectParser(BERTags.SET, false); + _nextObject = null; + + return certs; + } + + return null; + } + + public ASN1SetParser getCrls() + throws IOException + { + if (!_certsCalled) + { + throw new IOException("getCerts() has not been called."); + } + + _crlsCalled = true; + + if (_nextObject == null) + { + _nextObject = _seq.readObject(); + } + + if (_nextObject instanceof ASN1TaggedObjectParser && ((ASN1TaggedObjectParser)_nextObject).getTagNo() == 1) + { + ASN1SetParser crls = (ASN1SetParser)((ASN1TaggedObjectParser)_nextObject).getObjectParser(BERTags.SET, false); + _nextObject = null; + + return crls; + } + + return null; + } + + public ASN1SetParser getSignerInfos() + throws IOException + { + if (!_certsCalled || !_crlsCalled) + { + throw new IOException("getCerts() and/or getCrls() has not been called."); + } + + if (_nextObject == null) + { + _nextObject = _seq.readObject(); + } + + return (ASN1SetParser)_nextObject; + } +} diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/cms/TimeStampAndCRL.java b/bcprov/src/main/java/org/bouncycastle/asn1/cms/TimeStampAndCRL.java new file mode 100644 index 0000000..f6d8d5a --- /dev/null +++ b/bcprov/src/main/java/org/bouncycastle/asn1/cms/TimeStampAndCRL.java @@ -0,0 +1,96 @@ +package org.bouncycastle.asn1.cms; + +import org.bouncycastle.asn1.ASN1EncodableVector; +import org.bouncycastle.asn1.ASN1Object; +import org.bouncycastle.asn1.ASN1Primitive; +import org.bouncycastle.asn1.ASN1Sequence; +import org.bouncycastle.asn1.DERSequence; +import org.bouncycastle.asn1.x509.CertificateList; + +/** + * <a href="http://tools.ietf.org/html/rfc5544">RFC 5544</a> + * Binding Documents with Time-Stamps; TimeStampAndCRL object. + * <pre> + * TimeStampAndCRL ::= SEQUENCE { + * timeStamp TimeStampToken, -- according to RFC 3161 + * crl CertificateList OPTIONAL -- according to RFC 5280 + * } + * </pre> + */ +public class TimeStampAndCRL + extends ASN1Object +{ + private ContentInfo timeStamp; + private CertificateList crl; + + public TimeStampAndCRL(ContentInfo timeStamp) + { + this.timeStamp = timeStamp; + } + + private TimeStampAndCRL(ASN1Sequence seq) + { + this.timeStamp = ContentInfo.getInstance(seq.getObjectAt(0)); + if (seq.size() == 2) + { + this.crl = CertificateList.getInstance(seq.getObjectAt(1)); + } + } + + /** + * Return a TimeStampAndCRL object from the given object. + * <p> + * Accepted inputs: + * <ul> + * <li> null → null + * <li> {@link TimeStampAndCRL} object + * <li> {@link org.bouncycastle.asn1.ASN1Sequence#getInstance(java.lang.Object) ASN1Sequence} input formats with TimeStampAndCRL structure inside + * </ul> + * + * @param obj the object we want converted. + * @exception IllegalArgumentException if the object cannot be converted. + */ + public static TimeStampAndCRL getInstance(Object obj) + { + if (obj instanceof TimeStampAndCRL) + { + return (TimeStampAndCRL)obj; + } + else if (obj != null) + { + return new TimeStampAndCRL(ASN1Sequence.getInstance(obj)); + } + + return null; + } + + public ContentInfo getTimeStampToken() + { + return this.timeStamp; + } + + /** @deprecated use getCRL() */ + public CertificateList getCertificateList() + { + return this.crl; + } + + public CertificateList getCRL() + { + return this.crl; + } + + public ASN1Primitive toASN1Primitive() + { + ASN1EncodableVector v = new ASN1EncodableVector(); + + v.add(timeStamp); + + if (crl != null) + { + v.add(crl); + } + + return new DERSequence(v); + } +} diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/cms/TimeStampTokenEvidence.java b/bcprov/src/main/java/org/bouncycastle/asn1/cms/TimeStampTokenEvidence.java new file mode 100644 index 0000000..5461147 --- /dev/null +++ b/bcprov/src/main/java/org/bouncycastle/asn1/cms/TimeStampTokenEvidence.java @@ -0,0 +1,98 @@ +package org.bouncycastle.asn1.cms; + +import java.util.Enumeration; + +import org.bouncycastle.asn1.ASN1EncodableVector; +import org.bouncycastle.asn1.ASN1Object; +import org.bouncycastle.asn1.ASN1Primitive; +import org.bouncycastle.asn1.ASN1Sequence; +import org.bouncycastle.asn1.ASN1TaggedObject; +import org.bouncycastle.asn1.DERSequence; + +/** + * <a href="http://tools.ietf.org/html/rfc5544">RFC 5544</a> + * Binding Documents with Time-Stamps; TimeStampTokenEvidence object. + * <pre> + * TimeStampTokenEvidence ::= + * SEQUENCE SIZE(1..MAX) OF TimeStampAndCRL + * </pre> + */ +public class TimeStampTokenEvidence + extends ASN1Object +{ + private TimeStampAndCRL[] timeStampAndCRLs; + + public TimeStampTokenEvidence(TimeStampAndCRL[] timeStampAndCRLs) + { + this.timeStampAndCRLs = timeStampAndCRLs; + } + + public TimeStampTokenEvidence(TimeStampAndCRL timeStampAndCRL) + { + this.timeStampAndCRLs = new TimeStampAndCRL[1]; + + timeStampAndCRLs[0] = timeStampAndCRL; + } + + private TimeStampTokenEvidence(ASN1Sequence seq) + { + this.timeStampAndCRLs = new TimeStampAndCRL[seq.size()]; + + int count = 0; + + for (Enumeration en = seq.getObjects(); en.hasMoreElements();) + { + timeStampAndCRLs[count++] = TimeStampAndCRL.getInstance(en.nextElement()); + } + } + + public static TimeStampTokenEvidence getInstance(ASN1TaggedObject tagged, boolean explicit) + { + return getInstance(ASN1Sequence.getInstance(tagged, explicit)); + } + + /** + * Return a TimeStampTokenEvidence object from the given object. + * <p> + * Accepted inputs: + * <ul> + * <li> null → null + * <li> {@link TimeStampTokenEvidence} object + * <li> {@link org.bouncycastle.asn1.ASN1Sequence#getInstance(java.lang.Object) ASN1Sequence} input formats with TimeStampTokenEvidence structure inside + * </ul> + * + * @param obj the object we want converted. + * @exception IllegalArgumentException if the object cannot be converted. + */ + public static TimeStampTokenEvidence getInstance(Object obj) + { + if (obj instanceof TimeStampTokenEvidence) + { + return (TimeStampTokenEvidence)obj; + } + else if (obj != null) + { + return new TimeStampTokenEvidence(ASN1Sequence.getInstance(obj)); + } + + return null; + } + + public TimeStampAndCRL[] toTimeStampAndCRLArray() + { + return timeStampAndCRLs; + } + + public ASN1Primitive toASN1Primitive() + { + ASN1EncodableVector v = new ASN1EncodableVector(); + + for (int i = 0; i != timeStampAndCRLs.length; i++) + { + v.add(timeStampAndCRLs[i]); + } + + return new DERSequence(v); + } + +} diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/cms/TimeStampedData.java b/bcprov/src/main/java/org/bouncycastle/asn1/cms/TimeStampedData.java new file mode 100644 index 0000000..f19061e --- /dev/null +++ b/bcprov/src/main/java/org/bouncycastle/asn1/cms/TimeStampedData.java @@ -0,0 +1,131 @@ +package org.bouncycastle.asn1.cms; + +import org.bouncycastle.asn1.ASN1EncodableVector; +import org.bouncycastle.asn1.ASN1Integer; +import org.bouncycastle.asn1.ASN1Object; +import org.bouncycastle.asn1.ASN1OctetString; +import org.bouncycastle.asn1.ASN1Primitive; +import org.bouncycastle.asn1.ASN1Sequence; +import org.bouncycastle.asn1.BERSequence; +import org.bouncycastle.asn1.DERIA5String; + +/** + * <a href="http://tools.ietf.org/html/rfc5544">RFC 5544</a>: + * Binding Documents with Time-Stamps; TimeStampedData object. + * <p> + * <pre> + * TimeStampedData ::= SEQUENCE { + * version INTEGER { v1(1) }, + * dataUri IA5String OPTIONAL, + * metaData MetaData OPTIONAL, + * content OCTET STRING OPTIONAL, + * temporalEvidence Evidence + * } + * </pre> + */ +public class TimeStampedData + extends ASN1Object +{ + private ASN1Integer version; + private DERIA5String dataUri; + private MetaData metaData; + private ASN1OctetString content; + private Evidence temporalEvidence; + + public TimeStampedData(DERIA5String dataUri, MetaData metaData, ASN1OctetString content, Evidence temporalEvidence) + { + this.version = new ASN1Integer(1); + this.dataUri = dataUri; + this.metaData = metaData; + this.content = content; + this.temporalEvidence = temporalEvidence; + } + + private TimeStampedData(ASN1Sequence seq) + { + this.version = ASN1Integer.getInstance(seq.getObjectAt(0)); + + int index = 1; + if (seq.getObjectAt(index) instanceof DERIA5String) + { + this.dataUri = DERIA5String.getInstance(seq.getObjectAt(index++)); + } + if (seq.getObjectAt(index) instanceof MetaData || seq.getObjectAt(index) instanceof ASN1Sequence) + { + this.metaData = MetaData.getInstance(seq.getObjectAt(index++)); + } + if (seq.getObjectAt(index) instanceof ASN1OctetString) + { + this.content = ASN1OctetString.getInstance(seq.getObjectAt(index++)); + } + this.temporalEvidence = Evidence.getInstance(seq.getObjectAt(index)); + } + + /** + * Return a TimeStampedData object from the given object. + * <p> + * Accepted inputs: + * <ul> + * <li> null → null + * <li> {@link RecipientKeyIdentifier} object + * <li> {@link org.bouncycastle.asn1.ASN1Sequence#getInstance(java.lang.Object) ASN1Sequence} input formats with TimeStampedData structure inside + * </ul> + * + * @param obj the object we want converted. + * @exception IllegalArgumentException if the object cannot be converted. + */ + public static TimeStampedData getInstance(Object obj) + { + if (obj == null || obj instanceof TimeStampedData) + { + return (TimeStampedData)obj; + } + return new TimeStampedData(ASN1Sequence.getInstance(obj)); + } + + public DERIA5String getDataUri() + { + return dataUri; + } + + public MetaData getMetaData() + { + return metaData; + } + + public ASN1OctetString getContent() + { + return content; + } + + public Evidence getTemporalEvidence() + { + return temporalEvidence; + } + + public ASN1Primitive toASN1Primitive() + { + ASN1EncodableVector v = new ASN1EncodableVector(); + + v.add(version); + + if (dataUri != null) + { + v.add(dataUri); + } + + if (metaData != null) + { + v.add(metaData); + } + + if (content != null) + { + v.add(content); + } + + v.add(temporalEvidence); + + return new BERSequence(v); + } +} diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/cms/TimeStampedDataParser.java b/bcprov/src/main/java/org/bouncycastle/asn1/cms/TimeStampedDataParser.java new file mode 100644 index 0000000..f53e00f --- /dev/null +++ b/bcprov/src/main/java/org/bouncycastle/asn1/cms/TimeStampedDataParser.java @@ -0,0 +1,141 @@ +package org.bouncycastle.asn1.cms; + +import java.io.IOException; + +import org.bouncycastle.asn1.ASN1Encodable; +import org.bouncycastle.asn1.ASN1EncodableVector; +import org.bouncycastle.asn1.ASN1Integer; +import org.bouncycastle.asn1.ASN1OctetStringParser; +import org.bouncycastle.asn1.ASN1Primitive; +import org.bouncycastle.asn1.ASN1Sequence; +import org.bouncycastle.asn1.ASN1SequenceParser; +import org.bouncycastle.asn1.BERSequence; +import org.bouncycastle.asn1.DERIA5String; + +/** + * Parser for <a href="http://tools.ietf.org/html/rfc5544">RFC 5544</a>: + * {@link TimeStampedData} object. + * <p> + * <pre> + * TimeStampedData ::= SEQUENCE { + * version INTEGER { v1(1) }, + * dataUri IA5String OPTIONAL, + * metaData MetaData OPTIONAL, + * content OCTET STRING OPTIONAL, + * temporalEvidence Evidence + * } + * </pre> + */ +public class TimeStampedDataParser +{ + private ASN1Integer version; + private DERIA5String dataUri; + private MetaData metaData; + private ASN1OctetStringParser content; + private Evidence temporalEvidence; + private ASN1SequenceParser parser; + + private TimeStampedDataParser(ASN1SequenceParser parser) + throws IOException + { + this.parser = parser; + this.version = ASN1Integer.getInstance(parser.readObject()); + + ASN1Encodable obj = parser.readObject(); + + if (obj instanceof DERIA5String) + { + this.dataUri = DERIA5String.getInstance(obj); + obj = parser.readObject(); + } + if (obj instanceof MetaData || obj instanceof ASN1SequenceParser) + { + this.metaData = MetaData.getInstance(obj.toASN1Primitive()); + obj = parser.readObject(); + } + if (obj instanceof ASN1OctetStringParser) + { + this.content = (ASN1OctetStringParser)obj; + } + } + + public static TimeStampedDataParser getInstance(Object obj) + throws IOException + { + if (obj instanceof ASN1Sequence) + { + return new TimeStampedDataParser(((ASN1Sequence)obj).parser()); + } + if (obj instanceof ASN1SequenceParser) + { + return new TimeStampedDataParser((ASN1SequenceParser)obj); + } + + return null; + } + + public DERIA5String getDataUri() + { + return dataUri; + } + + public MetaData getMetaData() + { + return metaData; + } + + public ASN1OctetStringParser getContent() + { + return content; + } + + public Evidence getTemporalEvidence() + throws IOException + { + if (temporalEvidence == null) + { + temporalEvidence = Evidence.getInstance(parser.readObject().toASN1Primitive()); + } + + return temporalEvidence; + } + + /** + * <pre> + * TimeStampedData ::= SEQUENCE { + * version INTEGER { v1(1) }, + * dataUri IA5String OPTIONAL, + * metaData MetaData OPTIONAL, + * content OCTET STRING OPTIONAL, + * temporalEvidence Evidence + * } + * </pre> + * @return + * @deprecated will be removed + */ + public ASN1Primitive toASN1Primitive() + { + ASN1EncodableVector v = new ASN1EncodableVector(); + + v.add(version); + + if (dataUri != null) + { + v.add(dataUri); + } + + if (metaData != null) + { + v.add(metaData); + } + + if (content != null) + { + v.add(content); + } + + v.add(temporalEvidence); + + return new BERSequence(v); + } +} diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/cms/ecc/MQVuserKeyingMaterial.java b/bcprov/src/main/java/org/bouncycastle/asn1/cms/ecc/MQVuserKeyingMaterial.java new file mode 100644 index 0000000..bd7267b --- /dev/null +++ b/bcprov/src/main/java/org/bouncycastle/asn1/cms/ecc/MQVuserKeyingMaterial.java @@ -0,0 +1,122 @@ +package org.bouncycastle.asn1.cms.ecc; + +import org.bouncycastle.asn1.ASN1EncodableVector; +import org.bouncycastle.asn1.ASN1Object; +import org.bouncycastle.asn1.ASN1OctetString; +import org.bouncycastle.asn1.ASN1Primitive; +import org.bouncycastle.asn1.ASN1Sequence; +import org.bouncycastle.asn1.ASN1TaggedObject; +import org.bouncycastle.asn1.DERSequence; +import org.bouncycastle.asn1.DERTaggedObject; +import org.bouncycastle.asn1.cms.OriginatorPublicKey; + +/** + * <a href="http://tools.ietf.org/html/rfc5753">RFC 5753/3278</a>: MQVuserKeyingMaterial object. + * <pre> + * MQVuserKeyingMaterial ::= SEQUENCE { + * ephemeralPublicKey OriginatorPublicKey, + * addedukm [0] EXPLICIT UserKeyingMaterial OPTIONAL } + * </pre> + */ +public class MQVuserKeyingMaterial + extends ASN1Object +{ + private OriginatorPublicKey ephemeralPublicKey; + private ASN1OctetString addedukm; + + public MQVuserKeyingMaterial( + OriginatorPublicKey ephemeralPublicKey, + ASN1OctetString addedukm) + { + // TODO Check ephemeralPublicKey not null + + this.ephemeralPublicKey = ephemeralPublicKey; + this.addedukm = addedukm; + } + + private MQVuserKeyingMaterial( + ASN1Sequence seq) + { + // TODO Check seq has either 1 or 2 elements + + this.ephemeralPublicKey = OriginatorPublicKey.getInstance( + seq.getObjectAt(0)); + + if (seq.size() > 1) + { + this.addedukm = ASN1OctetString.getInstance( + (ASN1TaggedObject)seq.getObjectAt(1), true); + } + } + + /** + * Return an MQVuserKeyingMaterial object from a tagged object. + * + * @param obj the tagged object holding the object we want. + * @param explicit true if the object is meant to be explicitly + * tagged false otherwise. + * @throws IllegalArgumentException if the object held by the + * tagged object cannot be converted. + */ + public static MQVuserKeyingMaterial getInstance( + ASN1TaggedObject obj, + boolean explicit) + { + return getInstance(ASN1Sequence.getInstance(obj, explicit)); + } + + /** + * Return an MQVuserKeyingMaterial object from the given object. + * <p> + * Accepted inputs: + * <ul> + * <li> null → null + * <li> {@link MQVuserKeyingMaterial} object + * <li> {@link org.bouncycastle.asn1.ASN1Sequence ASN1Sequence} with MQVuserKeyingMaterial inside it. + * </ul> + * + * @param obj the object we want converted. + * @throws IllegalArgumentException if the object cannot be converted. + */ + public static MQVuserKeyingMaterial getInstance( + Object obj) + { + if (obj == null || obj instanceof MQVuserKeyingMaterial) + { + return (MQVuserKeyingMaterial)obj; + } + + if (obj instanceof ASN1Sequence) + { + return new MQVuserKeyingMaterial((ASN1Sequence)obj); + } + + throw new IllegalArgumentException("Invalid MQVuserKeyingMaterial: " + obj.getClass().getName()); + } + + public OriginatorPublicKey getEphemeralPublicKey() + { + return ephemeralPublicKey; + } + + public ASN1OctetString getAddedukm() + { + return addedukm; + } + + /** + * Produce an object suitable for an ASN1OutputStream. + */ + public ASN1Primitive toASN1Primitive() + { + ASN1EncodableVector v = new ASN1EncodableVector(); + v.add(ephemeralPublicKey); + + if (addedukm != null) + { + v.add(new DERTaggedObject(true, 0, addedukm)); + } + + return new DERSequence(v); + } +} diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/cms/ecc/package.html b/bcprov/src/main/java/org/bouncycastle/asn1/cms/ecc/package.html new file mode 100644 index 0000000..9d33025 --- /dev/null +++ b/bcprov/src/main/java/org/bouncycastle/asn1/cms/ecc/package.html @@ -0,0 +1,5 @@ +<html> +<body bgcolor="#ffffff"> +Support classes for CMS ECC - RFC 5753/3278. +</body> +</html> diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/cms/package.html b/bcprov/src/main/java/org/bouncycastle/asn1/cms/package.html new file mode 100644 index 0000000..c165a7a --- /dev/null +++ b/bcprov/src/main/java/org/bouncycastle/asn1/cms/package.html @@ -0,0 +1,5 @@ +<html> +<body bgcolor="#ffffff"> +Support classes useful for encoding and supporting Cryptographic Message Syntax as described in PKCS#7 and RFC 3369 (formerly RFC 2630). +</body> +</html> |