diff --git a/pkix/src/main/java/org/bouncycastle/cms/CMSAuthEnvelopedData.java b/pkix/src/main/java/org/bouncycastle/cms/CMSAuthEnvelopedData.java index 770f8d5287..f1edc92993 100644 --- a/pkix/src/main/java/org/bouncycastle/cms/CMSAuthEnvelopedData.java +++ b/pkix/src/main/java/org/bouncycastle/cms/CMSAuthEnvelopedData.java @@ -3,7 +3,9 @@ import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.InputStream; +import java.io.OutputStream; +import org.bouncycastle.asn1.ASN1Encoding; import org.bouncycastle.asn1.ASN1ObjectIdentifier; import org.bouncycastle.asn1.ASN1Set; import org.bouncycastle.asn1.cms.AttributeTable; @@ -23,23 +25,26 @@ public class CMSAuthEnvelopedData RecipientInformationStore recipientInfoStore; ContentInfo contentInfo; - private OriginatorInformation originatorInfo; - private AlgorithmIdentifier authEncAlg; - private ASN1Set authAttrs; - private byte[] mac; - private ASN1Set unauthAttrs; + private OriginatorInformation originatorInfo; + private AlgorithmIdentifier authEncAlg; + private ASN1Set authAttrs; + private byte[] mac; + private ASN1Set unauthAttrs; - public CMSAuthEnvelopedData(byte[] authEnvData) throws CMSException + public CMSAuthEnvelopedData(byte[] authEnvData) + throws CMSException { this(CMSUtils.readContentInfo(authEnvData)); } - public CMSAuthEnvelopedData(InputStream authEnvData) throws CMSException + public CMSAuthEnvelopedData(InputStream authEnvData) + throws CMSException { this(CMSUtils.readContentInfo(authEnvData)); } - public CMSAuthEnvelopedData(ContentInfo contentInfo) throws CMSException + public CMSAuthEnvelopedData(ContentInfo contentInfo) + throws CMSException { this.contentInfo = contentInfo; @@ -63,17 +68,58 @@ public CMSAuthEnvelopedData(ContentInfo contentInfo) throws CMSException this.mac = authEnvData.getMac().getOctets(); - CMSSecureReadable secureReadable = new CMSSecureReadable() + CMSSecureReadable secureReadable = new CMSSecureReadableWithAAD() { + private OutputStream aadStream; + + @Override + public ASN1Set getAuthAttrSet() + { + return authAttrs; + } + + @Override + public void setAuthAttrSet(ASN1Set set) + { + + } + + @Override + public boolean hasAdditionalData() + { + return (aadStream != null && authAttrs != null); + } + public ASN1ObjectIdentifier getContentType() { return authEncInfo.getContentType(); } public InputStream getInputStream() - throws IOException, CMSException + throws IOException + { + if (aadStream != null && authAttrs != null) + { + aadStream.write(authAttrs.getEncoded(ASN1Encoding.DER)); + } + return new InputStreamWithMAC(new ByteArrayInputStream(authEncInfo.getEncryptedContent().getOctets()), mac); + } + + @Override + public void setAADStream(OutputStream stream) { - return new ByteArrayInputStream(Arrays.concatenate(authEncInfo.getEncryptedContent().getOctets(), mac)); + aadStream = stream; + } + + public OutputStream getAADStream() + { + return aadStream; + } + + @Override + public byte[] getMAC() + { + return Arrays.clone(mac); } }; @@ -84,27 +130,8 @@ public InputStream getInputStream() // // build the RecipientInformationStore // - if (authAttrs != null) - { - this.recipientInfoStore = CMSEnvelopedHelper.buildRecipientInformationStore( - recipientInfos, this.authEncAlg, secureReadable, new AuthAttributesProvider() - { - public ASN1Set getAuthAttributes() - { - return authAttrs; - } - - public boolean isAead() - { - return true; - } - }); - } - else - { - this.recipientInfoStore = CMSEnvelopedHelper.buildRecipientInformationStore( - recipientInfos, this.authEncAlg, secureReadable); - } + this.recipientInfoStore = CMSEnvelopedHelper.buildRecipientInformationStore( + recipientInfos, this.authEncAlg, secureReadable); } /** @@ -128,6 +155,7 @@ public RecipientInformationStore getRecipientInfos() /** * return a table of the authenticated attributes (as in those used to provide associated data) indexed by * the OID of the attribute. + * * @return the authenticated attributes. */ public AttributeTable getAuthAttrs() @@ -143,6 +171,7 @@ public AttributeTable getAuthAttrs() /** * return a table of the unauthenticated attributes indexed by * the OID of the attribute. + * * @return the unauthenticated attributes. */ public AttributeTable getUnauthAttrs() @@ -157,6 +186,7 @@ public AttributeTable getUnauthAttrs() /** * Return the MAC value that was originally calculated for this AuthEnveloped data. + * * @return the MAC data associated with the stream. */ public byte[] getMac() diff --git a/pkix/src/main/java/org/bouncycastle/cms/CMSAuthEnvelopedDataGenerator.java b/pkix/src/main/java/org/bouncycastle/cms/CMSAuthEnvelopedDataGenerator.java index 976603d303..e84f2a69af 100644 --- a/pkix/src/main/java/org/bouncycastle/cms/CMSAuthEnvelopedDataGenerator.java +++ b/pkix/src/main/java/org/bouncycastle/cms/CMSAuthEnvelopedDataGenerator.java @@ -3,24 +3,15 @@ import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.OutputStream; -import java.util.Collections; -import java.util.Iterator; import org.bouncycastle.asn1.ASN1EncodableVector; -import org.bouncycastle.asn1.ASN1Encoding; -import org.bouncycastle.asn1.ASN1OctetString; import org.bouncycastle.asn1.ASN1Set; -import org.bouncycastle.asn1.BEROctetString; import org.bouncycastle.asn1.DEROctetString; import org.bouncycastle.asn1.DERSet; -import org.bouncycastle.asn1.DLSet; -import org.bouncycastle.asn1.cms.AttributeTable; import org.bouncycastle.asn1.cms.AuthEnvelopedData; import org.bouncycastle.asn1.cms.CMSObjectIdentifiers; import org.bouncycastle.asn1.cms.ContentInfo; import org.bouncycastle.asn1.cms.EncryptedContentInfo; -import org.bouncycastle.asn1.x509.AlgorithmIdentifier; -import org.bouncycastle.operator.GenericKey; import org.bouncycastle.operator.OutputAEADEncryptor; public class CMSAuthEnvelopedDataGenerator @@ -38,26 +29,17 @@ private CMSAuthEnvelopedData doGenerate( OutputAEADEncryptor contentEncryptor) throws CMSException { - ASN1EncodableVector recipientInfos = new ASN1EncodableVector(); - AlgorithmIdentifier encAlgId; - ASN1OctetString encContent; + ASN1EncodableVector recipientInfos = CMSUtils.getRecipentInfos(contentEncryptor.getKey(), recipientInfoGenerators); ByteArrayOutputStream bOut = new ByteArrayOutputStream(); - ASN1Set authenticatedAttrSet = null; + ASN1Set authenticatedAttrSet; try { OutputStream cOut = contentEncryptor.getOutputStream(bOut); content.write(cOut); - - if (authAttrsGenerator != null) - { - AttributeTable attrTable = authAttrsGenerator.getAttributes(Collections.EMPTY_MAP); - authenticatedAttrSet = new DERSet(attrTable.toASN1EncodableVector()); - - contentEncryptor.getAADStream().write(authenticatedAttrSet.getEncoded(ASN1Encoding.DER)); - } + authenticatedAttrSet = CMSUtils.processAuthAttrSet(authAttrsGenerator, contentEncryptor); cOut.close(); } @@ -69,35 +51,13 @@ private CMSAuthEnvelopedData doGenerate( byte[] encryptedContent = bOut.toByteArray(); byte[] mac = contentEncryptor.getMAC(); - encAlgId = contentEncryptor.getAlgorithmIdentifier(); - - encContent = new BEROctetString(encryptedContent); - - GenericKey encKey = contentEncryptor.getKey(); + EncryptedContentInfo eci = CMSUtils.getEncryptedContentInfo(content, contentEncryptor, encryptedContent); - for (Iterator it = recipientInfoGenerators.iterator(); it.hasNext();) - { - RecipientInfoGenerator recipient = (RecipientInfoGenerator)it.next(); - - recipientInfos.add(recipient.generate(encKey)); - } - - EncryptedContentInfo eci = new EncryptedContentInfo( - content.getContentType(), - encAlgId, - encContent); - - ASN1Set unprotectedAttrSet = null; - if (unauthAttrsGenerator != null) - { - AttributeTable attrTable = unauthAttrsGenerator.getAttributes(Collections.EMPTY_MAP); - - unprotectedAttrSet = new DLSet(attrTable.toASN1EncodableVector()); - } + ASN1Set unprotectedAttrSet = CMSUtils.getAttrDLSet(unauthAttrsGenerator); ContentInfo contentInfo = new ContentInfo( - CMSObjectIdentifiers.authEnvelopedData, - new AuthEnvelopedData(originatorInfo, new DERSet(recipientInfos), eci, authenticatedAttrSet, new DEROctetString(mac), unprotectedAttrSet)); + CMSObjectIdentifiers.authEnvelopedData, + new AuthEnvelopedData(originatorInfo, new DERSet(recipientInfos), eci, authenticatedAttrSet, new DEROctetString(mac), unprotectedAttrSet)); return new CMSAuthEnvelopedData(contentInfo); } diff --git a/pkix/src/main/java/org/bouncycastle/cms/CMSAuthEnvelopedDataParser.java b/pkix/src/main/java/org/bouncycastle/cms/CMSAuthEnvelopedDataParser.java new file mode 100644 index 0000000000..4012f1e8bf --- /dev/null +++ b/pkix/src/main/java/org/bouncycastle/cms/CMSAuthEnvelopedDataParser.java @@ -0,0 +1,299 @@ +package org.bouncycastle.cms; + +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; + +import org.bouncycastle.asn1.ASN1Encoding; +import org.bouncycastle.asn1.ASN1ObjectIdentifier; +import org.bouncycastle.asn1.ASN1OctetString; +import org.bouncycastle.asn1.ASN1OctetStringParser; +import org.bouncycastle.asn1.ASN1SequenceParser; +import org.bouncycastle.asn1.ASN1Set; +import org.bouncycastle.asn1.ASN1SetParser; +import org.bouncycastle.asn1.BERTags; +import org.bouncycastle.asn1.cms.AttributeTable; +import org.bouncycastle.asn1.cms.AuthEnvelopedDataParser; +import org.bouncycastle.asn1.cms.CMSAttributes; +import org.bouncycastle.asn1.cms.EncryptedContentInfoParser; +import org.bouncycastle.asn1.cms.OriginatorInfo; +import org.bouncycastle.asn1.x509.AlgorithmIdentifier; +import org.bouncycastle.util.Arrays; + +public class CMSAuthEnvelopedDataParser + extends CMSContentInfoParser +{ + private final RecipientInformationStore recipientInfoStore; + private final AuthEnvelopedDataParser authEvnData; + private final LocalMacProvider localMacProvider; + private final AlgorithmIdentifier encAlg; + private AttributeTable authAttrs; + private ASN1Set authAttrSet; + private AttributeTable unauthAttrs; + + private boolean authAttrNotRead; + private boolean unauthAttrNotRead; + private OriginatorInformation originatorInfo; + + public CMSAuthEnvelopedDataParser( + byte[] envelopedData) + throws CMSException, IOException + { + this(new ByteArrayInputStream(envelopedData)); + } + + public CMSAuthEnvelopedDataParser( + InputStream envelopedData) + throws CMSException, IOException + { + super(envelopedData); + + authAttrNotRead = true; + unauthAttrNotRead = true; + authEvnData = new AuthEnvelopedDataParser((ASN1SequenceParser)_contentInfo.getContent(BERTags.SEQUENCE)); + + OriginatorInfo info = authEvnData.getOriginatorInfo(); + + if (info != null) + { + this.originatorInfo = new OriginatorInformation(info); + } + // + // read the recipients + // + ASN1Set recipientInfos = ASN1Set.getInstance(authEvnData.getRecipientInfos().toASN1Primitive()); + + EncryptedContentInfoParser encInfo = authEvnData.getAuthEncryptedContentInfo(); + encAlg = encInfo.getContentEncryptionAlgorithm(); + localMacProvider = new LocalMacProvider(authEvnData, this); + + CMSReadable readable = new CMSProcessableInputStream(new InputStreamWithMAC( + ((ASN1OctetStringParser)encInfo.getEncryptedContent(BERTags.OCTET_STRING)).getOctetStream(), localMacProvider)); + + CMSSecureReadableWithAAD secureReadable = new CMSSecureReadableWithAAD() + { + private OutputStream aadStream; + + @Override + public ASN1ObjectIdentifier getContentType() + { + return encInfo.getContentType(); + } + + @Override + public InputStream getInputStream() + throws IOException, CMSException + { + return readable.getInputStream(); + } + + @Override + public ASN1Set getAuthAttrSet() + { + return authAttrSet; + } + + @Override + public void setAuthAttrSet(ASN1Set set) + { + + } + + @Override + public boolean hasAdditionalData() + { + return true; + } + + @Override + public void setAADStream(OutputStream stream) + { + aadStream = stream; + } + + @Override + public OutputStream getAADStream() + { + return aadStream; + } + + @Override + public byte[] getMAC() + { + return Arrays.clone(localMacProvider.getMAC()); + } + }; + + localMacProvider.setSecureReadable(secureReadable); + // + // build the RecipientInformationStore + // + this.recipientInfoStore = CMSEnvelopedHelper.buildRecipientInformationStore(recipientInfos, this.encAlg, secureReadable); + } + + /** + * Return the originator information associated with this message if present. + * + * @return OriginatorInformation, null if not present. + */ + public OriginatorInformation getOriginatorInfo() + { + return originatorInfo; + } + + /** + * Return the MAC algorithm details for the MAC associated with the data in this object. + * + * @return AlgorithmIdentifier representing the MAC algorithm. + */ + public AlgorithmIdentifier getEncryptionAlgOID() + { + return encAlg; + } + + /** + * return the object identifier for the mac algorithm. + */ + public String getEncAlgOID() + { + return encAlg.getAlgorithm().toString(); + } + + /** + * return the ASN.1 encoded encryption algorithm parameters, or null if + * there aren't any. + */ + public byte[] getEncAlgParams() + { + try + { + return CMSUtils.encodeObj(encAlg.getParameters()); + } + catch (Exception e) + { + throw new RuntimeException("exception getting encryption parameters " + e); + } + } + + /** + * return a store of the intended recipients for this message + */ + public RecipientInformationStore getRecipientInfos() + { + return recipientInfoStore; + } + + public byte[] getMac() + throws IOException + { + return Arrays.clone(localMacProvider.getMAC()); + } + + private ASN1Set getAuthAttrSet() + throws IOException + { + if (authAttrs == null && authAttrNotRead) + { + ASN1SetParser set = authEvnData.getAuthAttrs(); + + if (set != null) + { + authAttrSet = (ASN1Set)set.toASN1Primitive(); + } + + authAttrNotRead = false; + } + + return authAttrSet; + } + + /** + * return a table of the unauthenticated attributes indexed by + * the OID of the attribute. + */ + public AttributeTable getAuthAttrs() + throws IOException + { + if (authAttrs == null && authAttrNotRead) + { + ASN1Set set = getAuthAttrSet(); + + if (set != null) + { + authAttrs = new AttributeTable(set); + } + } + + return authAttrs; + } + + /** + * return a table of the unauthenticated attributes indexed by + * the OID of the attribute. + */ + public AttributeTable getUnauthAttrs() + throws IOException + { + if (unauthAttrs == null && unauthAttrNotRead) + { + unauthAttrNotRead = false; + unauthAttrs = CMSUtils.getAttributesTable(authEvnData.getUnauthAttrs()); + } + + return unauthAttrs; + } + + /** + * This will only be valid after the content has been read. + * + * @return the contents of the messageDigest attribute, if available. Null if not present. + */ + public byte[] getContentDigest() + { + if (authAttrs != null) + { + return ASN1OctetString.getInstance(authAttrs.get(CMSAttributes.messageDigest).getAttrValues().getObjectAt(0)).getOctets(); + } + + return null; + } + + static class LocalMacProvider + implements MACProvider + { + private byte[] mac; + private final AuthEnvelopedDataParser authEnvData; + private final CMSAuthEnvelopedDataParser parser; + private CMSSecureReadableWithAAD readable; + + LocalMacProvider(AuthEnvelopedDataParser authEnvData, CMSAuthEnvelopedDataParser parser) + { + this.authEnvData = authEnvData; + this.parser = parser; + } + + public void init() + throws IOException + { + parser.authAttrs = parser.getAuthAttrs(); + if (parser.authAttrs != null) + { + readable.setAuthAttrSet(parser.authAttrSet); + readable.getAADStream().write(parser.authAttrs.toASN1Structure().getEncoded(ASN1Encoding.DER)); + } + mac = authEnvData.getMac().getOctets(); + } + + void setSecureReadable(CMSSecureReadableWithAAD secureReadable) + { + readable = secureReadable; + } + + public byte[] getMAC() + { + return mac; + } + } +} + diff --git a/pkix/src/main/java/org/bouncycastle/cms/CMSAuthEnvelopedDataStreamGenerator.java b/pkix/src/main/java/org/bouncycastle/cms/CMSAuthEnvelopedDataStreamGenerator.java new file mode 100644 index 0000000000..4e27d034ad --- /dev/null +++ b/pkix/src/main/java/org/bouncycastle/cms/CMSAuthEnvelopedDataStreamGenerator.java @@ -0,0 +1,201 @@ +package org.bouncycastle.cms; + +import java.io.IOException; +import java.io.OutputStream; +import java.util.Collections; + +import org.bouncycastle.asn1.ASN1EncodableVector; +import org.bouncycastle.asn1.ASN1Integer; +import org.bouncycastle.asn1.ASN1ObjectIdentifier; +import org.bouncycastle.asn1.ASN1Set; +import org.bouncycastle.asn1.BERSequenceGenerator; +import org.bouncycastle.asn1.DEROctetString; +import org.bouncycastle.asn1.DERTaggedObject; +import org.bouncycastle.asn1.cms.AuthenticatedData; +import org.bouncycastle.asn1.cms.CMSObjectIdentifiers; +import org.bouncycastle.asn1.x509.AlgorithmIdentifier; +import org.bouncycastle.operator.OutputAEADEncryptor; + +public class CMSAuthEnvelopedDataStreamGenerator + extends CMSAuthEnvelopedGenerator +{ + + private int _bufferSize; + private boolean _berEncodeRecipientSet; + + public CMSAuthEnvelopedDataStreamGenerator() + { + + } + + /** + * Set the underlying string size for encapsulated data + * + * @param bufferSize length of octet strings to buffer the data. + */ + public void setBufferSize( + int bufferSize) + { + _bufferSize = bufferSize; + } + + /** + * Use a BER Set to store the recipient information + */ + public void setBEREncodeRecipients( + boolean berEncodeRecipientSet) + { + _berEncodeRecipientSet = berEncodeRecipientSet; + } + + private OutputStream doOpen( + ASN1ObjectIdentifier dataType, + OutputStream out, + OutputAEADEncryptor encryptor) + throws IOException, CMSException + { + ASN1EncodableVector recipientInfos = CMSUtils.getRecipentInfos(encryptor.getKey(), recipientInfoGenerators); + + return open(dataType, out, recipientInfos, encryptor); + } + + protected OutputStream open( + ASN1ObjectIdentifier dataType, + OutputStream out, + ASN1EncodableVector recipientInfos, + OutputAEADEncryptor encryptor) + throws IOException + { + // + // ContentInfo + // + BERSequenceGenerator cGen = new BERSequenceGenerator(out); + + cGen.addObject(CMSObjectIdentifiers.authEnvelopedData); + + // + // Encrypted Data + // + BERSequenceGenerator authEnvGen = new BERSequenceGenerator(cGen.getRawOutputStream(), 0, true); + + authEnvGen.addObject(new ASN1Integer(AuthenticatedData.calculateVersion(originatorInfo))); + + CMSUtils.addOriginatorInfoToGenerator(authEnvGen, originatorInfo); + + CMSUtils.addRecipientInfosToGenerator(recipientInfos, authEnvGen, _berEncodeRecipientSet); + + BERSequenceGenerator eiGen = new BERSequenceGenerator(authEnvGen.getRawOutputStream()); + + eiGen.addObject(dataType); + + AlgorithmIdentifier encAlgId = encryptor.getAlgorithmIdentifier(); + + eiGen.getRawOutputStream().write(encAlgId.getEncoded()); + + OutputStream octetStream = CMSUtils.createBEROctetOutputStream( + eiGen.getRawOutputStream(), 0, true, _bufferSize); + + return new CMSAuthEnvelopedDataOutputStream(encryptor, octetStream, cGen, authEnvGen, eiGen); + } + + protected OutputStream open( + OutputStream out, + ASN1EncodableVector recipientInfos, + OutputAEADEncryptor encryptor) + throws CMSException + { + try + { + return open(CMSObjectIdentifiers.data, out, recipientInfos, encryptor); + } + catch (IOException e) + { + throw new CMSException("exception decoding algorithm parameters.", e); + } + } + + + /** + * generate an enveloped object that contains an CMS Enveloped Data + * object using the given encryptor. + */ + public OutputStream open( + OutputStream out, + OutputAEADEncryptor encryptor) + throws CMSException, IOException + { + return doOpen(new ASN1ObjectIdentifier(CMSObjectIdentifiers.data.getId()), out, encryptor); + } + + private class CMSAuthEnvelopedDataOutputStream + extends OutputStream + { + private final OutputAEADEncryptor _encryptor; + private final OutputStream _cOut; + private final OutputStream _octetStream; + private final BERSequenceGenerator _cGen; + private final BERSequenceGenerator _envGen; + private final BERSequenceGenerator _eiGen; + + public CMSAuthEnvelopedDataOutputStream( + OutputAEADEncryptor encryptor, + OutputStream octetStream, + BERSequenceGenerator cGen, + BERSequenceGenerator envGen, + BERSequenceGenerator eiGen) + { + _encryptor = encryptor; + _octetStream = octetStream; + _cOut = encryptor.getOutputStream(octetStream); + _cGen = cGen; + _envGen = envGen; + _eiGen = eiGen; + } + + public void write( + int b) + throws IOException + { + _cOut.write(b); + } + + public void write( + byte[] bytes, + int off, + int len) + throws IOException + { + _cOut.write(bytes, off, len); + } + + public void write( + byte[] bytes) + throws IOException + { + _cOut.write(bytes); + } + + public void close() + throws IOException + { + ASN1Set authenticatedAttrSet = CMSUtils.processAuthAttrSet(authAttrsGenerator, _encryptor); + + _cOut.close(); + _octetStream.close(); + _eiGen.close(); + + if (authenticatedAttrSet != null) + { + _envGen.addObject(new DERTaggedObject(false, 1, authenticatedAttrSet)); + } + + _envGen.addObject(new DEROctetString(_encryptor.getMAC())); + + CMSUtils.addAttriSetToGenerator(_envGen, unauthAttrsGenerator, 2, Collections.EMPTY_MAP); + + _envGen.close(); + _cGen.close(); + } + } + +} diff --git a/pkix/src/main/java/org/bouncycastle/cms/CMSAuthenticatedData.java b/pkix/src/main/java/org/bouncycastle/cms/CMSAuthenticatedData.java index f09c555b25..20356ce51d 100644 --- a/pkix/src/main/java/org/bouncycastle/cms/CMSAuthenticatedData.java +++ b/pkix/src/main/java/org/bouncycastle/cms/CMSAuthenticatedData.java @@ -3,7 +3,6 @@ import java.io.IOException; import java.io.InputStream; -import org.bouncycastle.asn1.ASN1Encodable; import org.bouncycastle.asn1.ASN1EncodableVector; import org.bouncycastle.asn1.ASN1OctetString; import org.bouncycastle.asn1.ASN1Set; @@ -145,19 +144,8 @@ public CMSAuthenticatedData( try { CMSSecureReadable secureReadable = new CMSEnvelopedHelper.CMSDigestAuthenticatedSecureReadable(digestCalculatorProvider.get(authData.getDigestAlgorithm()), encInfo.getContentType(), readable); - - this.recipientInfoStore = CMSEnvelopedHelper.buildRecipientInformationStore(recipientInfos, this.macAlg, secureReadable, new AuthAttributesProvider() - { - public ASN1Set getAuthAttributes() - { - return authAttrs; - } - - public boolean isAead() - { - return false; - } - }); + secureReadable.setAuthAttrSet(authAttrs); + this.recipientInfoStore = CMSEnvelopedHelper.buildRecipientInformationStore(recipientInfos, this.macAlg, secureReadable); } catch (OperatorCreationException e) { @@ -166,8 +154,7 @@ public boolean isAead() } else { - CMSSecureReadable secureReadable = new CMSEnvelopedHelper.CMSAuthenticatedSecureReadable(this.macAlg, encInfo.getContentType(), readable); - + CMSSecureReadable secureReadable = new CMSEnvelopedHelper.CMSAuthEnveSecureReadable(this.macAlg, encInfo.getContentType(), readable); this.recipientInfoStore = CMSEnvelopedHelper.buildRecipientInformationStore(recipientInfos, this.macAlg, secureReadable); } } @@ -187,18 +174,6 @@ public byte[] getMac() return Arrays.clone(mac); } - private byte[] encodeObj( - ASN1Encodable obj) - throws IOException - { - if (obj != null) - { - return obj.toASN1Primitive().getEncoded(); - } - - return null; - } - /** * Return the MAC algorithm details for the MAC associated with the data in this object. * @@ -225,7 +200,7 @@ public byte[] getMacAlgParams() { try { - return encodeObj(macAlg.getParameters()); + return CMSUtils.encodeObj(macAlg.getParameters()); } catch (Exception e) { diff --git a/pkix/src/main/java/org/bouncycastle/cms/CMSAuthenticatedDataGenerator.java b/pkix/src/main/java/org/bouncycastle/cms/CMSAuthenticatedDataGenerator.java index 3df2d46ea4..35bc6d151b 100644 --- a/pkix/src/main/java/org/bouncycastle/cms/CMSAuthenticatedDataGenerator.java +++ b/pkix/src/main/java/org/bouncycastle/cms/CMSAuthenticatedDataGenerator.java @@ -4,7 +4,6 @@ import java.io.IOException; import java.io.OutputStream; import java.util.Collections; -import java.util.Iterator; import java.util.Map; import org.bouncycastle.asn1.ASN1EncodableVector; @@ -12,7 +11,6 @@ import org.bouncycastle.asn1.ASN1OctetString; import org.bouncycastle.asn1.ASN1Set; import org.bouncycastle.asn1.BEROctetString; -import org.bouncycastle.asn1.BERSet; import org.bouncycastle.asn1.DEROctetString; import org.bouncycastle.asn1.DERSet; import org.bouncycastle.asn1.cms.AuthenticatedData; @@ -27,7 +25,7 @@ /** * General class for generating a CMS authenticated-data message. - * + *

* A simple example of usage. * *

@@ -52,7 +50,7 @@ public CMSAuthenticatedDataGenerator()
     /**
      * Generate an authenticated data object from the passed in typedData and MacCalculator.
      *
-     * @param typedData the data to have a MAC attached.
+     * @param typedData     the data to have a MAC attached.
      * @param macCalculator the calculator of the MAC to be attached.
      * @return the resulting CMSAuthenticatedData object.
      * @throws CMSException on failure in encoding data or processing recipients.
@@ -66,25 +64,19 @@ public CMSAuthenticatedData generate(CMSTypedData typedData, MacCalculator macCa
     /**
      * Generate an authenticated data object from the passed in typedData and MacCalculator.
      *
-     * @param typedData the data to have a MAC attached.
-     * @param macCalculator the calculator of the MAC to be attached.
+     * @param typedData        the data to have a MAC attached.
+     * @param macCalculator    the calculator of the MAC to be attached.
      * @param digestCalculator calculator for computing digest of the encapsulated data.
      * @return the resulting CMSAuthenticatedData object.
-     * @throws CMSException on failure in encoding data or processing recipients.    
+     * @throws CMSException on failure in encoding data or processing recipients.
      */
     public CMSAuthenticatedData generate(CMSTypedData typedData, MacCalculator macCalculator, final DigestCalculator digestCalculator)
         throws CMSException
     {
-        ASN1EncodableVector     recipientInfos = new ASN1EncodableVector();
-        ASN1OctetString         encContent;
-        ASN1OctetString         macResult;
+        ASN1OctetString encContent;
+        ASN1OctetString macResult;
 
-        for (Iterator it = recipientInfoGenerators.iterator(); it.hasNext();)
-        {
-            RecipientInfoGenerator recipient = (RecipientInfoGenerator)it.next();
-
-            recipientInfos.add(recipient.generate(macCalculator.getKey()));
-        }
+        ASN1EncodableVector recipientInfos = CMSUtils.getRecipentInfos(macCalculator.getKey(), recipientInfoGenerators);
 
         AuthenticatedData authData;
 
@@ -128,11 +120,11 @@ public CMSAuthenticatedData generate(CMSTypedData typedData, MacCalculator macCa
             {
                 throw new CMSException("unable to perform MAC calculation: " + e.getMessage(), e);
             }
-            ASN1Set unauthed = (unauthGen != null) ? new BERSet(unauthGen.getAttributes(parameters).toASN1EncodableVector()) : null;
+            ASN1Set unauthed = CMSUtils.getAttrBERSet(unauthGen);
 
-            ContentInfo  eci = new ContentInfo(
-                            typedData.getContentType(),
-                            encContent);
+            ContentInfo eci = new ContentInfo(
+                typedData.getContentType(),
+                encContent);
 
             authData = new AuthenticatedData(originatorInfo, new DERSet(recipientInfos), macCalculator.getAlgorithmIdentifier(), digestCalculator.getAlgorithmIdentifier(), eci, authed, macResult, unauthed);
         }
@@ -140,7 +132,7 @@ public CMSAuthenticatedData generate(CMSTypedData typedData, MacCalculator macCa
         {
             try
             {
-                ByteArrayOutputStream   bOut = new ByteArrayOutputStream();
+                ByteArrayOutputStream bOut = new ByteArrayOutputStream();
                 OutputStream mOut = new TeeOutputStream(bOut, macCalculator.getOutputStream());
 
                 typedData.write(mOut);
@@ -156,17 +148,17 @@ public CMSAuthenticatedData generate(CMSTypedData typedData, MacCalculator macCa
                 throw new CMSException("unable to perform MAC calculation: " + e.getMessage(), e);
             }
 
-            ASN1Set unauthed = (unauthGen != null) ? new BERSet(unauthGen.getAttributes(Collections.EMPTY_MAP).toASN1EncodableVector()) : null;
+            ASN1Set unauthed = CMSUtils.getAttrBERSet(unauthGen);
 
-            ContentInfo  eci = new ContentInfo(
-                            typedData.getContentType(),
-                            encContent);
+            ContentInfo eci = new ContentInfo(
+                typedData.getContentType(),
+                encContent);
 
             authData = new AuthenticatedData(originatorInfo, new DERSet(recipientInfos), macCalculator.getAlgorithmIdentifier(), null, eci, null, macResult, unauthed);
         }
 
         ContentInfo contentInfo = new ContentInfo(
-                CMSObjectIdentifiers.authenticatedData, authData);
+            CMSObjectIdentifiers.authenticatedData, authData);
 
         return new CMSAuthenticatedData(contentInfo, new DigestCalculatorProvider()
         {
diff --git a/pkix/src/main/java/org/bouncycastle/cms/CMSAuthenticatedDataParser.java b/pkix/src/main/java/org/bouncycastle/cms/CMSAuthenticatedDataParser.java
index 175592520b..9750850141 100644
--- a/pkix/src/main/java/org/bouncycastle/cms/CMSAuthenticatedDataParser.java
+++ b/pkix/src/main/java/org/bouncycastle/cms/CMSAuthenticatedDataParser.java
@@ -4,15 +4,12 @@
 import java.io.IOException;
 import java.io.InputStream;
 
-import org.bouncycastle.asn1.ASN1Encodable;
-import org.bouncycastle.asn1.ASN1EncodableVector;
 import org.bouncycastle.asn1.ASN1OctetString;
 import org.bouncycastle.asn1.ASN1OctetStringParser;
 import org.bouncycastle.asn1.ASN1SequenceParser;
 import org.bouncycastle.asn1.ASN1Set;
 import org.bouncycastle.asn1.ASN1SetParser;
 import org.bouncycastle.asn1.BERTags;
-import org.bouncycastle.asn1.DERSet;
 import org.bouncycastle.asn1.cms.AttributeTable;
 import org.bouncycastle.asn1.cms.AuthenticatedDataParser;
 import org.bouncycastle.asn1.cms.CMSAttributes;
@@ -53,12 +50,12 @@
  *          }
  *      }
  *  
- * Note: this class does not introduce buffering - if you are processing large files you should create - * the parser with: - *
+ * Note: this class does not introduce buffering - if you are processing large files you should create
+ * the parser with:
+ * 
  *          CMSAuthenticatedDataParser     ep = new CMSAuthenticatedDataParser(new BufferedInputStream(inputStream, bufSize));
  *  
- * where bufSize is a suitably large buffer size. + * where bufSize is a suitably large buffer size. */ public class CMSAuthenticatedDataParser extends CMSContentInfoParser @@ -76,6 +73,8 @@ public class CMSAuthenticatedDataParser private boolean unauthAttrNotRead; private OriginatorInformation originatorInfo; + private CMSSecureReadable secureReadable; + public CMSAuthenticatedDataParser( byte[] envelopedData) throws CMSException, IOException @@ -145,27 +144,9 @@ public CMSAuthenticatedDataParser( try { - CMSSecureReadable secureReadable = new CMSEnvelopedHelper.CMSDigestAuthenticatedSecureReadable(digestCalculatorProvider.get(digestAlgorithm), data.getContentType(), readable); - - this.recipientInfoStore = CMSEnvelopedHelper.buildRecipientInformationStore(recipientInfos, this.macAlg, secureReadable, new AuthAttributesProvider() - { - public ASN1Set getAuthAttributes() - { - try - { - return getAuthAttrSet(); - } - catch (IOException e) - { - throw new IllegalStateException("can't parse authenticated attributes!"); - } - } - - public boolean isAead() - { - return false; - } - }); + secureReadable = new CMSEnvelopedHelper.CMSDigestAuthenticatedSecureReadable(digestCalculatorProvider.get(digestAlgorithm), data.getContentType(), readable); + + this.recipientInfoStore = CMSEnvelopedHelper.buildRecipientInformationStore(recipientInfos, this.macAlg, secureReadable); } catch (OperatorCreationException e) { @@ -181,7 +162,7 @@ public boolean isAead() CMSReadable readable = new CMSProcessableInputStream( ((ASN1OctetStringParser)data.getContent(BERTags.OCTET_STRING)).getOctetStream()); - CMSSecureReadable secureReadable = new CMSEnvelopedHelper.CMSAuthenticatedSecureReadable(this.macAlg, data.getContentType(), readable); + secureReadable = new CMSEnvelopedHelper.CMSAuthEnveSecureReadable(this.macAlg, data.getContentType(), readable); this.recipientInfoStore = CMSEnvelopedHelper.buildRecipientInformationStore(recipientInfos, this.macAlg, secureReadable); } @@ -225,7 +206,7 @@ public byte[] getMacAlgParams() { try { - return encodeObj(macAlg.getParameters()); + return CMSUtils.encodeObj(macAlg.getParameters()); } catch (Exception e) { @@ -265,6 +246,7 @@ private ASN1Set getAuthAttrSet() } authAttrNotRead = false; + secureReadable.setAuthAttrSet(authAttrSet); } return authAttrSet; @@ -273,7 +255,8 @@ private ASN1Set getAuthAttrSet() /** * return a table of the unauthenticated attributes indexed by * the OID of the attribute. - * @exception java.io.IOException + * + * @throws java.io.IOException */ public AttributeTable getAuthAttrs() throws IOException @@ -294,48 +277,21 @@ public AttributeTable getAuthAttrs() /** * return a table of the unauthenticated attributes indexed by * the OID of the attribute. - * @exception java.io.IOException + * + * @throws java.io.IOException */ public AttributeTable getUnauthAttrs() throws IOException { if (unauthAttrs == null && unauthAttrNotRead) { - ASN1SetParser set = authData.getUnauthAttrs(); - unauthAttrNotRead = false; - - if (set != null) - { - ASN1EncodableVector v = new ASN1EncodableVector(); - ASN1Encodable o; - - while ((o = set.readObject()) != null) - { - ASN1SequenceParser seq = (ASN1SequenceParser)o; - - v.add(seq.toASN1Primitive()); - } - - unauthAttrs = new AttributeTable(new DERSet(v)); - } + unauthAttrs = CMSUtils.getAttributesTable(authData.getUnauthAttrs()); } return unauthAttrs; } - private byte[] encodeObj( - ASN1Encodable obj) - throws IOException - { - if (obj != null) - { - return obj.toASN1Primitive().getEncoded(); - } - - return null; - } - /** * This will only be valid after the content has been read. * diff --git a/pkix/src/main/java/org/bouncycastle/cms/CMSAuthenticatedDataStreamGenerator.java b/pkix/src/main/java/org/bouncycastle/cms/CMSAuthenticatedDataStreamGenerator.java index 16c4334d4b..93f56c197d 100644 --- a/pkix/src/main/java/org/bouncycastle/cms/CMSAuthenticatedDataStreamGenerator.java +++ b/pkix/src/main/java/org/bouncycastle/cms/CMSAuthenticatedDataStreamGenerator.java @@ -3,7 +3,6 @@ import java.io.IOException; import java.io.OutputStream; import java.util.Collections; -import java.util.Iterator; import java.util.Map; import org.bouncycastle.asn1.ASN1EncodableVector; @@ -12,7 +11,6 @@ import org.bouncycastle.asn1.ASN1ObjectIdentifier; import org.bouncycastle.asn1.ASN1Set; import org.bouncycastle.asn1.BERSequenceGenerator; -import org.bouncycastle.asn1.BERSet; import org.bouncycastle.asn1.DEROctetString; import org.bouncycastle.asn1.DERSet; import org.bouncycastle.asn1.DERTaggedObject; @@ -139,14 +137,7 @@ public OutputStream open( try { - ASN1EncodableVector recipientInfos = new ASN1EncodableVector(); - - for (Iterator it = recipientInfoGenerators.iterator(); it.hasNext();) - { - RecipientInfoGenerator recipient = (RecipientInfoGenerator)it.next(); - - recipientInfos.add(recipient.generate(macCalculator.getKey())); - } + ASN1EncodableVector recipientInfos = CMSUtils.getRecipentInfos(macCalculator.getKey(), recipientInfoGenerators); // // ContentInfo @@ -162,19 +153,9 @@ public OutputStream open( authGen.addObject(new ASN1Integer(AuthenticatedData.calculateVersion(originatorInfo))); - if (originatorInfo != null) - { - authGen.addObject(new DERTaggedObject(false, 0, originatorInfo)); - } + CMSUtils.addOriginatorInfoToGenerator(authGen, originatorInfo); - if (berEncodeRecipientSet) - { - authGen.getRawOutputStream().write(new BERSet(recipientInfos).getEncoded()); - } - else - { - authGen.getRawOutputStream().write(new DERSet(recipientInfos).getEncoded()); - } + CMSUtils.addRecipientInfosToGenerator(recipientInfos, authGen, berEncodeRecipientSet); AlgorithmIdentifier macAlgId = macCalculator.getAlgorithmIdentifier(); @@ -297,10 +278,7 @@ public void close() envGen.addObject(new DEROctetString(macCalculator.getMac())); - if (unauthGen != null) - { - envGen.addObject(new DERTaggedObject(false, 3, new BERSet(unauthGen.getAttributes(parameters).toASN1EncodableVector()))); - } + CMSUtils.addAttriSetToGenerator(envGen, unauthGen, 3 , parameters); envGen.close(); cGen.close(); diff --git a/pkix/src/main/java/org/bouncycastle/cms/CMSEncryptedDataGenerator.java b/pkix/src/main/java/org/bouncycastle/cms/CMSEncryptedDataGenerator.java index cdb800b0ca..9e17d5c1c6 100644 --- a/pkix/src/main/java/org/bouncycastle/cms/CMSEncryptedDataGenerator.java +++ b/pkix/src/main/java/org/bouncycastle/cms/CMSEncryptedDataGenerator.java @@ -3,13 +3,10 @@ import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.OutputStream; -import java.util.Collections; import org.bouncycastle.asn1.ASN1OctetString; import org.bouncycastle.asn1.ASN1Set; import org.bouncycastle.asn1.BEROctetString; -import org.bouncycastle.asn1.BERSet; -import org.bouncycastle.asn1.cms.AttributeTable; import org.bouncycastle.asn1.cms.CMSObjectIdentifiers; import org.bouncycastle.asn1.cms.ContentInfo; import org.bouncycastle.asn1.cms.EncryptedContentInfo; @@ -78,13 +75,7 @@ private CMSEncryptedData doGenerate( encAlgId, encContent); - ASN1Set unprotectedAttrSet = null; - if (unprotectedAttributeGenerator != null) - { - AttributeTable attrTable = unprotectedAttributeGenerator.getAttributes(Collections.EMPTY_MAP); - - unprotectedAttrSet = new BERSet(attrTable.toASN1EncodableVector()); - } + ASN1Set unprotectedAttrSet = CMSUtils.getAttrBERSet(unprotectedAttributeGenerator); ContentInfo contentInfo = new ContentInfo( CMSObjectIdentifiers.encryptedData, diff --git a/pkix/src/main/java/org/bouncycastle/cms/CMSEnvelopedData.java b/pkix/src/main/java/org/bouncycastle/cms/CMSEnvelopedData.java index 0baed09f0e..189ed242a9 100644 --- a/pkix/src/main/java/org/bouncycastle/cms/CMSEnvelopedData.java +++ b/pkix/src/main/java/org/bouncycastle/cms/CMSEnvelopedData.java @@ -3,7 +3,6 @@ import java.io.IOException; import java.io.InputStream; -import org.bouncycastle.asn1.ASN1Encodable; import org.bouncycastle.asn1.ASN1Set; import org.bouncycastle.asn1.cms.AttributeTable; import org.bouncycastle.asn1.cms.ContentInfo; @@ -90,7 +89,7 @@ public CMSEnvelopedData( EncryptedContentInfo encInfo = envData.getEncryptedContentInfo(); this.encAlg = encInfo.getContentEncryptionAlgorithm(); CMSReadable readable = new CMSProcessableByteArray(encInfo.getEncryptedContent().getOctets()); - CMSSecureReadable secureReadable = new CMSEnvelopedHelper.CMSEnvelopedSecureReadable( + CMSSecureReadable secureReadable = new CMSEnvelopedHelper.CMSAuthEnveSecureReadable( this.encAlg, encInfo.getContentType(), readable); // @@ -111,18 +110,6 @@ public CMSEnvelopedData( } } - private byte[] encodeObj( - ASN1Encodable obj) - throws IOException - { - if (obj != null) - { - return obj.toASN1Primitive().getEncoded(); - } - - return null; - } - /** * Return the originator information associated with this message if present. * @@ -159,7 +146,7 @@ public byte[] getEncryptionAlgParams() { try { - return encodeObj(encAlg.getParameters()); + return CMSUtils.encodeObj(encAlg.getParameters()); } catch (Exception e) { diff --git a/pkix/src/main/java/org/bouncycastle/cms/CMSEnvelopedDataGenerator.java b/pkix/src/main/java/org/bouncycastle/cms/CMSEnvelopedDataGenerator.java index 84dad0155a..24c925a650 100644 --- a/pkix/src/main/java/org/bouncycastle/cms/CMSEnvelopedDataGenerator.java +++ b/pkix/src/main/java/org/bouncycastle/cms/CMSEnvelopedDataGenerator.java @@ -3,22 +3,14 @@ import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.OutputStream; -import java.util.Collections; -import java.util.Iterator; import org.bouncycastle.asn1.ASN1EncodableVector; -import org.bouncycastle.asn1.ASN1OctetString; import org.bouncycastle.asn1.ASN1Set; -import org.bouncycastle.asn1.BEROctetString; -import org.bouncycastle.asn1.BERSet; import org.bouncycastle.asn1.DERSet; -import org.bouncycastle.asn1.cms.AttributeTable; import org.bouncycastle.asn1.cms.CMSObjectIdentifiers; import org.bouncycastle.asn1.cms.ContentInfo; import org.bouncycastle.asn1.cms.EncryptedContentInfo; import org.bouncycastle.asn1.cms.EnvelopedData; -import org.bouncycastle.asn1.x509.AlgorithmIdentifier; -import org.bouncycastle.operator.GenericKey; import org.bouncycastle.operator.OutputAEADEncryptor; import org.bouncycastle.operator.OutputEncryptor; @@ -56,9 +48,7 @@ private CMSEnvelopedData doGenerate( OutputEncryptor contentEncryptor) throws CMSException { - ASN1EncodableVector recipientInfos = new ASN1EncodableVector(); - AlgorithmIdentifier encAlgId; - ASN1OctetString encContent; + ASN1EncodableVector recipientInfos = CMSUtils.getRecipentInfos(contentEncryptor.getKey(), recipientInfoGenerators); ByteArrayOutputStream bOut = new ByteArrayOutputStream(); @@ -84,35 +74,13 @@ private CMSEnvelopedData doGenerate( byte[] encryptedContent = bOut.toByteArray(); - encAlgId = contentEncryptor.getAlgorithmIdentifier(); + EncryptedContentInfo eci = CMSUtils.getEncryptedContentInfo(content, contentEncryptor, encryptedContent); - encContent = new BEROctetString(encryptedContent); - - GenericKey encKey = contentEncryptor.getKey(); - - for (Iterator it = recipientInfoGenerators.iterator(); it.hasNext();) - { - RecipientInfoGenerator recipient = (RecipientInfoGenerator)it.next(); - - recipientInfos.add(recipient.generate(encKey)); - } - - EncryptedContentInfo eci = new EncryptedContentInfo( - content.getContentType(), - encAlgId, - encContent); - - ASN1Set unprotectedAttrSet = null; - if (unprotectedAttributeGenerator != null) - { - AttributeTable attrTable = unprotectedAttributeGenerator.getAttributes(Collections.EMPTY_MAP); - - unprotectedAttrSet = new BERSet(attrTable.toASN1EncodableVector()); - } + ASN1Set unprotectedAttrSet = CMSUtils.getAttrBERSet(unprotectedAttributeGenerator); ContentInfo contentInfo = new ContentInfo( - CMSObjectIdentifiers.envelopedData, - new EnvelopedData(originatorInfo, new DERSet(recipientInfos), eci, unprotectedAttrSet)); + CMSObjectIdentifiers.envelopedData, + new EnvelopedData(originatorInfo, new DERSet(recipientInfos), eci, unprotectedAttrSet)); return new CMSEnvelopedData(contentInfo); } diff --git a/pkix/src/main/java/org/bouncycastle/cms/CMSEnvelopedDataParser.java b/pkix/src/main/java/org/bouncycastle/cms/CMSEnvelopedDataParser.java index dfb53de26f..c288452b40 100644 --- a/pkix/src/main/java/org/bouncycastle/cms/CMSEnvelopedDataParser.java +++ b/pkix/src/main/java/org/bouncycastle/cms/CMSEnvelopedDataParser.java @@ -4,14 +4,10 @@ import java.io.IOException; import java.io.InputStream; -import org.bouncycastle.asn1.ASN1Encodable; -import org.bouncycastle.asn1.ASN1EncodableVector; import org.bouncycastle.asn1.ASN1OctetStringParser; import org.bouncycastle.asn1.ASN1SequenceParser; import org.bouncycastle.asn1.ASN1Set; -import org.bouncycastle.asn1.ASN1SetParser; import org.bouncycastle.asn1.BERTags; -import org.bouncycastle.asn1.DERSet; import org.bouncycastle.asn1.cms.AttributeTable; import org.bouncycastle.asn1.cms.EncryptedContentInfoParser; import org.bouncycastle.asn1.cms.EnvelopedDataParser; @@ -99,7 +95,7 @@ public CMSEnvelopedDataParser( this.encAlg = encInfo.getContentEncryptionAlgorithm(); CMSReadable readable = new CMSProcessableInputStream( ((ASN1OctetStringParser)encInfo.getEncryptedContent(BERTags.OCTET_STRING)).getOctetStream()); - CMSSecureReadable secureReadable = new CMSEnvelopedHelper.CMSEnvelopedSecureReadable( + CMSSecureReadable secureReadable = new CMSEnvelopedHelper.CMSAuthEnveSecureReadable( this.encAlg, encInfo.getContentType(), readable); // @@ -125,7 +121,7 @@ public byte[] getEncryptionAlgParams() { try { - return encodeObj(encAlg.getParameters()); + return CMSUtils.encodeObj(encAlg.getParameters()); } catch (Exception e) { @@ -171,38 +167,10 @@ public AttributeTable getUnprotectedAttributes() { if (unprotectedAttributes == null && attrNotRead) { - ASN1SetParser set = envelopedData.getUnprotectedAttrs(); - attrNotRead = false; - - if (set != null) - { - ASN1EncodableVector v = new ASN1EncodableVector(); - ASN1Encodable o; - - while ((o = set.readObject()) != null) - { - ASN1SequenceParser seq = (ASN1SequenceParser)o; - - v.add(seq.toASN1Primitive()); - } - - unprotectedAttributes = new AttributeTable(new DERSet(v)); - } + unprotectedAttributes = CMSUtils.getAttributesTable(envelopedData.getUnprotectedAttrs()); } return unprotectedAttributes; } - - private byte[] encodeObj( - ASN1Encodable obj) - throws IOException - { - if (obj != null) - { - return obj.toASN1Primitive().getEncoded(); - } - - return null; - } } diff --git a/pkix/src/main/java/org/bouncycastle/cms/CMSEnvelopedDataStreamGenerator.java b/pkix/src/main/java/org/bouncycastle/cms/CMSEnvelopedDataStreamGenerator.java index d9651f5da8..0dc648160a 100644 --- a/pkix/src/main/java/org/bouncycastle/cms/CMSEnvelopedDataStreamGenerator.java +++ b/pkix/src/main/java/org/bouncycastle/cms/CMSEnvelopedDataStreamGenerator.java @@ -3,22 +3,15 @@ import java.io.IOException; import java.io.OutputStream; import java.util.Collections; -import java.util.Iterator; import org.bouncycastle.asn1.ASN1EncodableVector; import org.bouncycastle.asn1.ASN1Integer; import org.bouncycastle.asn1.ASN1ObjectIdentifier; -import org.bouncycastle.asn1.ASN1Set; import org.bouncycastle.asn1.BERSequenceGenerator; -import org.bouncycastle.asn1.BERSet; -import org.bouncycastle.asn1.DERSet; -import org.bouncycastle.asn1.DERTaggedObject; import org.bouncycastle.asn1.DLSet; -import org.bouncycastle.asn1.cms.AttributeTable; import org.bouncycastle.asn1.cms.CMSObjectIdentifiers; import org.bouncycastle.asn1.cms.EnvelopedData; import org.bouncycastle.asn1.x509.AlgorithmIdentifier; -import org.bouncycastle.operator.GenericKey; import org.bouncycastle.operator.OutputAEADEncryptor; import org.bouncycastle.operator.OutputEncryptor; @@ -32,12 +25,12 @@ * edGen.addRecipientInfoGenerator(new JceKeyTransRecipientInfoGenerator(recipientCert).setProvider("BC")); * * ByteArrayOutputStream bOut = new ByteArrayOutputStream(); - * + * * OutputStream out = edGen.open( * bOut, new JceCMSContentEncryptorBuilder(CMSAlgorithm.DES_EDE3_CBC) * .setProvider("BC").build()); * out.write(data); - * + * * out.close(); *
*/ @@ -56,7 +49,7 @@ public CMSEnvelopedDataStreamGenerator() /** * Set the underlying string size for encapsulated data - * + * * @param bufferSize length of octet strings to buffer the data. */ public void setBufferSize( @@ -90,16 +83,7 @@ private OutputStream doOpen( OutputEncryptor encryptor) throws IOException, CMSException { - ASN1EncodableVector recipientInfos = new ASN1EncodableVector(); - GenericKey encKey = encryptor.getKey(); - Iterator it = recipientInfoGenerators.iterator(); - - while (it.hasNext()) - { - RecipientInfoGenerator recipient = (RecipientInfoGenerator)it.next(); - - recipientInfos.add(recipient.generate(encKey)); - } + ASN1EncodableVector recipientInfos = CMSUtils.getRecipentInfos(encryptor.getKey(), recipientInfoGenerators); return open(dataType, out, recipientInfos, encryptor); } @@ -125,19 +109,9 @@ protected OutputStream open( envGen.addObject(getVersion(recipientInfos)); - if (originatorInfo != null) - { - envGen.addObject(new DERTaggedObject(false, 0, originatorInfo)); - } + CMSUtils.addOriginatorInfoToGenerator(envGen, originatorInfo); - if (_berEncodeRecipientSet) - { - envGen.getRawOutputStream().write(new BERSet(recipientInfos).getEncoded()); - } - else - { - envGen.getRawOutputStream().write(new DERSet(recipientInfos).getEncoded()); - } + CMSUtils.addRecipientInfosToGenerator(recipientInfos, envGen, _berEncodeRecipientSet); BERSequenceGenerator eiGen = new BERSequenceGenerator(envGen.getRawOutputStream()); @@ -161,49 +135,7 @@ protected OutputStream open( { try { - // - // ContentInfo - // - BERSequenceGenerator cGen = new BERSequenceGenerator(out); - - cGen.addObject(CMSObjectIdentifiers.envelopedData); - - // - // Encrypted Data - // - BERSequenceGenerator envGen = new BERSequenceGenerator(cGen.getRawOutputStream(), 0, true); - - ASN1Set recipients; - if (_berEncodeRecipientSet) - { - recipients = new BERSet(recipientInfos); - } - else - { - recipients = new DERSet(recipientInfos); - } - - envGen.addObject(getVersion(recipientInfos)); - - if (originatorInfo != null) - { - envGen.addObject(new DERTaggedObject(false, 0, originatorInfo)); - } - - envGen.getRawOutputStream().write(recipients.getEncoded()); - - BERSequenceGenerator eiGen = new BERSequenceGenerator(envGen.getRawOutputStream()); - - eiGen.addObject(CMSObjectIdentifiers.data); - - AlgorithmIdentifier encAlgId = encryptor.getAlgorithmIdentifier(); - - eiGen.getRawOutputStream().write(encAlgId.getEncoded()); - - OutputStream octetStream = CMSUtils.createBEROctetOutputStream( - eiGen.getRawOutputStream(), 0, false, _bufferSize); - - return new CmsEnvelopedDataOutputStream(encryptor, octetStream, cGen, envGen, eiGen); + return open(CMSObjectIdentifiers.data, out, recipientInfos, encryptor); } catch (IOException e) { @@ -246,7 +178,7 @@ private class CmsEnvelopedDataOutputStream private BERSequenceGenerator _cGen; private BERSequenceGenerator _envGen; private BERSequenceGenerator _eiGen; - + public CmsEnvelopedDataOutputStream( OutputEncryptor encryptor, OutputStream octetStream, @@ -261,14 +193,14 @@ public CmsEnvelopedDataOutputStream( _envGen = envGen; _eiGen = eiGen; } - + public void write( int b) throws IOException { _cOut.write(b); } - + public void write( byte[] bytes, int off, @@ -277,14 +209,14 @@ public void write( { _cOut.write(bytes, off, len); } - + public void write( byte[] bytes) throws IOException { _cOut.write(bytes); } - + public void close() throws IOException { @@ -297,15 +229,8 @@ public void close() } _eiGen.close(); - if (unprotectedAttributeGenerator != null) - { - AttributeTable attrTable = unprotectedAttributeGenerator.getAttributes(Collections.EMPTY_MAP); - - ASN1Set unprotectedAttrs = new BERSet(attrTable.toASN1EncodableVector()); + CMSUtils.addAttriSetToGenerator(_envGen, unprotectedAttributeGenerator, 1, Collections.EMPTY_MAP); - _envGen.addObject(new DERTaggedObject(false, 1, unprotectedAttrs)); - } - _envGen.close(); _cGen.close(); } diff --git a/pkix/src/main/java/org/bouncycastle/cms/CMSEnvelopedHelper.java b/pkix/src/main/java/org/bouncycastle/cms/CMSEnvelopedHelper.java index fd4d8b2f6a..05ada70595 100644 --- a/pkix/src/main/java/org/bouncycastle/cms/CMSEnvelopedHelper.java +++ b/pkix/src/main/java/org/bouncycastle/cms/CMSEnvelopedHelper.java @@ -24,31 +24,25 @@ class CMSEnvelopedHelper { static RecipientInformationStore buildRecipientInformationStore( ASN1Set recipientInfos, AlgorithmIdentifier messageAlgorithm, CMSSecureReadable secureReadable) - { - return buildRecipientInformationStore(recipientInfos, messageAlgorithm, secureReadable, null); - } - - static RecipientInformationStore buildRecipientInformationStore( - ASN1Set recipientInfos, AlgorithmIdentifier messageAlgorithm, CMSSecureReadable secureReadable, AuthAttributesProvider additionalData) { List infos = new ArrayList(); for (int i = 0; i != recipientInfos.size(); i++) { RecipientInfo info = RecipientInfo.getInstance(recipientInfos.getObjectAt(i)); - readRecipientInfo(infos, info, messageAlgorithm, secureReadable, additionalData); + readRecipientInfo(infos, info, messageAlgorithm, secureReadable); } return new RecipientInformationStore(infos); } private static void readRecipientInfo( - List infos, RecipientInfo info, AlgorithmIdentifier messageAlgorithm, CMSSecureReadable secureReadable, AuthAttributesProvider additionalData) + List infos, RecipientInfo info, AlgorithmIdentifier messageAlgorithm, CMSSecureReadable secureReadable) { ASN1Encodable recipInfo = info.getInfo(); if (recipInfo instanceof KeyTransRecipientInfo) { infos.add(new KeyTransRecipientInformation( - (KeyTransRecipientInfo)recipInfo, messageAlgorithm, secureReadable, additionalData)); + (KeyTransRecipientInfo)recipInfo, messageAlgorithm, secureReadable)); } else if (recipInfo instanceof OtherRecipientInfo) { @@ -56,36 +50,35 @@ else if (recipInfo instanceof OtherRecipientInfo) if (CMSObjectIdentifiers.id_ori_kem.equals(otherRecipientInfo.getType())) { infos.add(new KEMRecipientInformation( - KEMRecipientInfo.getInstance(otherRecipientInfo.getValue()), messageAlgorithm, secureReadable, additionalData)); + KEMRecipientInfo.getInstance(otherRecipientInfo.getValue()), messageAlgorithm, secureReadable)); } } else if (recipInfo instanceof KEKRecipientInfo) { infos.add(new KEKRecipientInformation( - (KEKRecipientInfo)recipInfo, messageAlgorithm, secureReadable, additionalData)); + (KEKRecipientInfo)recipInfo, messageAlgorithm, secureReadable)); } else if (recipInfo instanceof KeyAgreeRecipientInfo) { KeyAgreeRecipientInformation.readRecipientInfo(infos, - (KeyAgreeRecipientInfo)recipInfo, messageAlgorithm, secureReadable, additionalData); + (KeyAgreeRecipientInfo)recipInfo, messageAlgorithm, secureReadable); } else if (recipInfo instanceof PasswordRecipientInfo) { infos.add(new PasswordRecipientInformation( - (PasswordRecipientInfo)recipInfo, messageAlgorithm, secureReadable, additionalData)); + (PasswordRecipientInfo)recipInfo, messageAlgorithm, secureReadable)); } } - static class CMSDigestAuthenticatedSecureReadable + static abstract class CMSDefaultSecureReadable implements CMSSecureReadable { - private DigestCalculator digestCalculator; - private final ASN1ObjectIdentifier contentType; - private CMSReadable readable; + protected final ASN1ObjectIdentifier contentType; + protected CMSReadable readable; + protected ASN1Set authAttrSet; - public CMSDigestAuthenticatedSecureReadable(DigestCalculator digestCalculator, ASN1ObjectIdentifier contentType, CMSReadable readable) + CMSDefaultSecureReadable(ASN1ObjectIdentifier contentType, CMSReadable readable) { - this.digestCalculator = digestCalculator; this.contentType = contentType; this.readable = readable; } @@ -95,6 +88,31 @@ public ASN1ObjectIdentifier getContentType() return contentType; } + @Override + public ASN1Set getAuthAttrSet() + { + return authAttrSet; + } + + @Override + public void setAuthAttrSet(ASN1Set set) + { + authAttrSet = set; + } + + } + + static class CMSDigestAuthenticatedSecureReadable + extends CMSDefaultSecureReadable + { + private DigestCalculator digestCalculator; + + public CMSDigestAuthenticatedSecureReadable(DigestCalculator digestCalculator, ASN1ObjectIdentifier contentType, CMSReadable readable) + { + super(contentType, readable); + this.digestCalculator = digestCalculator; + } + public InputStream getInputStream() throws IOException, CMSException { @@ -117,7 +135,7 @@ public int read(byte[] inBuf, int inOff, int inLen) throws IOException { int n = in.read(inBuf, inOff, inLen); - + if (n >= 0) { digestCalculator.getOutputStream().write(inBuf, inOff, n); @@ -132,50 +150,23 @@ public byte[] getDigest() { return digestCalculator.getDigest(); } - } - - static class CMSAuthenticatedSecureReadable implements CMSSecureReadable - { - private AlgorithmIdentifier algorithm; - private final ASN1ObjectIdentifier contentType; - private CMSReadable readable; - - CMSAuthenticatedSecureReadable(AlgorithmIdentifier algorithm, ASN1ObjectIdentifier contentType, CMSReadable readable) - { - this.algorithm = algorithm; - this.contentType = contentType; - this.readable = readable; - } - public ASN1ObjectIdentifier getContentType() + @Override + public boolean hasAdditionalData() { - return contentType; + return true; } - - public InputStream getInputStream() - throws IOException, CMSException - { - return readable.getInputStream(); - } - } - static class CMSEnvelopedSecureReadable implements CMSSecureReadable + static class CMSAuthEnveSecureReadable + extends CMSDefaultSecureReadable { private AlgorithmIdentifier algorithm; - private final ASN1ObjectIdentifier contentType; - private CMSReadable readable; - CMSEnvelopedSecureReadable(AlgorithmIdentifier algorithm, ASN1ObjectIdentifier contentType, CMSReadable readable) + CMSAuthEnveSecureReadable(AlgorithmIdentifier algorithm, ASN1ObjectIdentifier contentType, CMSReadable readable) { + super(contentType, readable); this.algorithm = algorithm; - this.contentType = contentType; - this.readable = readable; - } - - public ASN1ObjectIdentifier getContentType() - { - return contentType; } public InputStream getInputStream() @@ -184,5 +175,10 @@ public InputStream getInputStream() return readable.getInputStream(); } + @Override + public boolean hasAdditionalData() + { + return false; + } } } diff --git a/pkix/src/main/java/org/bouncycastle/cms/CMSSecureReadable.java b/pkix/src/main/java/org/bouncycastle/cms/CMSSecureReadable.java index c99db78107..82f01ec796 100644 --- a/pkix/src/main/java/org/bouncycastle/cms/CMSSecureReadable.java +++ b/pkix/src/main/java/org/bouncycastle/cms/CMSSecureReadable.java @@ -4,6 +4,7 @@ import java.io.InputStream; import org.bouncycastle.asn1.ASN1ObjectIdentifier; +import org.bouncycastle.asn1.ASN1Set; interface CMSSecureReadable { @@ -11,4 +12,10 @@ interface CMSSecureReadable InputStream getInputStream() throws IOException, CMSException; + + ASN1Set getAuthAttrSet(); + + void setAuthAttrSet(ASN1Set set); + + boolean hasAdditionalData(); } diff --git a/pkix/src/main/java/org/bouncycastle/cms/CMSSecureReadableWithAAD.java b/pkix/src/main/java/org/bouncycastle/cms/CMSSecureReadableWithAAD.java new file mode 100644 index 0000000000..0c50efc895 --- /dev/null +++ b/pkix/src/main/java/org/bouncycastle/cms/CMSSecureReadableWithAAD.java @@ -0,0 +1,13 @@ +package org.bouncycastle.cms; + +import java.io.OutputStream; + +interface CMSSecureReadableWithAAD + extends CMSSecureReadable +{ + void setAADStream(OutputStream stream); + + OutputStream getAADStream(); + + byte[] getMAC(); +} diff --git a/pkix/src/main/java/org/bouncycastle/cms/CMSSignedDataGenerator.java b/pkix/src/main/java/org/bouncycastle/cms/CMSSignedDataGenerator.java index ab63c1d2d6..1bf5d393f2 100644 --- a/pkix/src/main/java/org/bouncycastle/cms/CMSSignedDataGenerator.java +++ b/pkix/src/main/java/org/bouncycastle/cms/CMSSignedDataGenerator.java @@ -217,33 +217,9 @@ public CMSSignedData generate( } } - ASN1Set certificates = null; + ASN1Set certificates = createSetFromList(certs, isDefiniteLength); - if (certs.size() != 0) - { - if (isDefiniteLength) - { - certificates = CMSUtils.createDlSetFromList(certs); - } - else - { - certificates = CMSUtils.createBerSetFromList(certs); - } - } - - ASN1Set certrevlist = null; - - if (crls.size() != 0) - { - if (isDefiniteLength) - { - certrevlist = CMSUtils.createDlSetFromList(crls); - } - else - { - certrevlist = CMSUtils.createBerSetFromList(crls); - } - } + ASN1Set certrevlist = createSetFromList(crls, isDefiniteLength); ContentInfo encInfo = new ContentInfo(contentTypeOID, octs); @@ -260,6 +236,15 @@ public CMSSignedData generate( return new CMSSignedData(content, contentInfo); } + private static ASN1Set createSetFromList(List list, boolean isDefiniteLength) + { + if(list.size()!=0) + { + return isDefiniteLength ? CMSUtils.createDlSetFromList(list) : CMSUtils.createBerSetFromList(list); + } + return null; + } + /** * generate a set of one or more SignerInformation objects representing counter signatures on * the passed in SignerInformation object. diff --git a/pkix/src/main/java/org/bouncycastle/cms/CMSUtils.java b/pkix/src/main/java/org/bouncycastle/cms/CMSUtils.java index bb74c5d9e5..5a11cedae8 100644 --- a/pkix/src/main/java/org/bouncycastle/cms/CMSUtils.java +++ b/pkix/src/main/java/org/bouncycastle/cms/CMSUtils.java @@ -5,25 +5,36 @@ import java.io.OutputStream; import java.util.ArrayList; import java.util.Collection; +import java.util.Collections; import java.util.HashSet; import java.util.Iterator; import java.util.List; +import java.util.Map; import java.util.Set; import org.bouncycastle.asn1.ASN1Encodable; import org.bouncycastle.asn1.ASN1EncodableVector; +import org.bouncycastle.asn1.ASN1Encoding; import org.bouncycastle.asn1.ASN1InputStream; import org.bouncycastle.asn1.ASN1ObjectIdentifier; +import org.bouncycastle.asn1.ASN1OctetString; +import org.bouncycastle.asn1.ASN1SequenceParser; import org.bouncycastle.asn1.ASN1Set; +import org.bouncycastle.asn1.ASN1SetParser; import org.bouncycastle.asn1.ASN1TaggedObject; +import org.bouncycastle.asn1.BEROctetString; import org.bouncycastle.asn1.BEROctetStringGenerator; +import org.bouncycastle.asn1.BERSequenceGenerator; import org.bouncycastle.asn1.BERSet; import org.bouncycastle.asn1.DERNull; import org.bouncycastle.asn1.DERSet; import org.bouncycastle.asn1.DERTaggedObject; import org.bouncycastle.asn1.DLSet; +import org.bouncycastle.asn1.cms.AttributeTable; import org.bouncycastle.asn1.cms.CMSObjectIdentifiers; import org.bouncycastle.asn1.cms.ContentInfo; +import org.bouncycastle.asn1.cms.EncryptedContentInfo; +import org.bouncycastle.asn1.cms.OriginatorInfo; import org.bouncycastle.asn1.cms.OtherRevocationInfoFormat; import org.bouncycastle.asn1.cryptopro.CryptoProObjectIdentifiers; import org.bouncycastle.asn1.ocsp.OCSPResponse; @@ -39,6 +50,9 @@ import org.bouncycastle.cert.X509CertificateHolder; import org.bouncycastle.operator.DigestAlgorithmIdentifierFinder; import org.bouncycastle.operator.DigestCalculator; +import org.bouncycastle.operator.GenericKey; +import org.bouncycastle.operator.OutputAEADEncryptor; +import org.bouncycastle.operator.OutputEncryptor; import org.bouncycastle.util.Store; import org.bouncycastle.util.Strings; import org.bouncycastle.util.io.Streams; @@ -407,4 +421,118 @@ static OutputStream getSafeTeeOutputStream(OutputStream s1, : s2 == null ? getSafeOutputStream(s1) : new TeeOutputStream( s1, s2); } + + static EncryptedContentInfo getEncryptedContentInfo(CMSTypedData content, OutputEncryptor contentEncryptor, byte[] encryptedContent) + throws CMSException + { + AlgorithmIdentifier encAlgId = contentEncryptor.getAlgorithmIdentifier(); + + ASN1OctetString encContent = new BEROctetString(encryptedContent); + + return new EncryptedContentInfo( + content.getContentType(), + encAlgId, + encContent); + } + + static ASN1EncodableVector getRecipentInfos(GenericKey encKey, List recipientInfoGenerators) + throws CMSException + { + ASN1EncodableVector recipientInfos = new ASN1EncodableVector(); + Iterator it = recipientInfoGenerators.iterator(); + + while (it.hasNext()) + { + RecipientInfoGenerator recipient = (RecipientInfoGenerator)it.next(); + + recipientInfos.add(recipient.generate(encKey)); + } + return recipientInfos; + } + + static void addRecipientInfosToGenerator(ASN1EncodableVector recipientInfos, BERSequenceGenerator authGen, boolean berEncodeRecipientSet) + throws IOException + { + if (berEncodeRecipientSet) + { + authGen.getRawOutputStream().write(new BERSet(recipientInfos).getEncoded()); + } + else + { + authGen.getRawOutputStream().write(new DERSet(recipientInfos).getEncoded()); + } + } + + static void addOriginatorInfoToGenerator(BERSequenceGenerator envGen, OriginatorInfo originatorInfo) + throws IOException + { + if (originatorInfo != null) + { + envGen.addObject(new DERTaggedObject(false, 0, originatorInfo)); + } + } + + static void addAttriSetToGenerator(BERSequenceGenerator gen, CMSAttributeTableGenerator attriGen, int tagNo, Map parameters) + throws IOException + { + if (attriGen != null) + { + gen.addObject(new DERTaggedObject(false, tagNo, new BERSet(attriGen.getAttributes(parameters).toASN1EncodableVector()))); + } + } + + static ASN1Set processAuthAttrSet(CMSAttributeTableGenerator authAttrsGenerator, OutputAEADEncryptor encryptor) + throws IOException + { + ASN1Set authenticatedAttrSet = null; + if (authAttrsGenerator != null) + { + AttributeTable attrTable = authAttrsGenerator.getAttributes(Collections.EMPTY_MAP); + + authenticatedAttrSet = new DERSet(attrTable.toASN1EncodableVector()); + encryptor.getAADStream().write(authenticatedAttrSet.getEncoded(ASN1Encoding.DER)); + } + return authenticatedAttrSet; + } + + static AttributeTable getAttributesTable(ASN1SetParser set) + throws IOException + { + if (set != null) + { + ASN1EncodableVector v = new ASN1EncodableVector(); + ASN1Encodable o; + + while ((o = set.readObject()) != null) + { + ASN1SequenceParser seq = (ASN1SequenceParser)o; + + v.add(seq.toASN1Primitive()); + } + return new AttributeTable(new DERSet(v)); + } + return null; + } + + static ASN1Set getAttrDLSet(CMSAttributeTableGenerator gen) + { + return (gen != null) ? new DLSet(gen.getAttributes(Collections.EMPTY_MAP).toASN1EncodableVector()) : null; + } + + static ASN1Set getAttrBERSet(CMSAttributeTableGenerator gen) + { + return (gen != null) ? new BERSet(gen.getAttributes(Collections.EMPTY_MAP).toASN1EncodableVector()) : null; + } + + static byte[] encodeObj( + ASN1Encodable obj) + throws IOException + { + if (obj != null) + { + return obj.toASN1Primitive().getEncoded(); + } + + return null; + } } diff --git a/pkix/src/main/java/org/bouncycastle/cms/InputStreamWithMAC.java b/pkix/src/main/java/org/bouncycastle/cms/InputStreamWithMAC.java new file mode 100644 index 0000000000..f789be0e2f --- /dev/null +++ b/pkix/src/main/java/org/bouncycastle/cms/InputStreamWithMAC.java @@ -0,0 +1,124 @@ +package org.bouncycastle.cms; + +import java.io.IOException; +import java.io.InputStream; + +import org.bouncycastle.util.Arrays; + +public final class InputStreamWithMAC + extends InputStream +{ + private final InputStream base; + private MACProvider macProvider; + private byte[] mac; + private boolean baseFinished; + private int index; + + InputStreamWithMAC(InputStream base, MACProvider macProvider) + { + this.base = base; + this.macProvider = macProvider; + + baseFinished = false; + index = 0; + } + + public InputStreamWithMAC(InputStream base, byte[] mac) + { + this.base = base; + this.mac = mac; + baseFinished = false; + index = 0; + } + + @Override + public int read() + throws IOException + { + int ch; + if (!baseFinished) + { + ch = base.read(); + if (ch < 0) + { + baseFinished = true; + if (macProvider != null) + { + macProvider.init(); + mac = macProvider.getMAC(); + } + return mac[index++] & 0xFF; + } + } + else + { + if (index >= mac.length) + { + return -1; + } + return mac[index++] & 0xFF; + } + return ch; + } + + public byte[] getMAC() + { + if (!baseFinished) + { + throw new IllegalStateException("input stream not fully processed"); + } + return Arrays.clone(mac); + + } + + @Override + public int read(byte[] b, int off, int len) + throws IOException + { + int ch; + if (!baseFinished) + { + ch = base.read(b, off, len); + if (ch < 0) + { + baseFinished = true; + if (macProvider != null) + { + macProvider.init(); + mac = macProvider.getMAC(); + } + if (len >= mac.length) + { + System.arraycopy(mac, 0, b, off, mac.length); + index = mac.length; + return mac.length; + } + else + { + System.arraycopy(mac, 0, b, off, len); + index += len; + return len; + } + } + return ch; + } + else if (index < mac.length) + { + if (len >= mac.length - index) + { + System.arraycopy(mac, index, b, off, mac.length - index); + int tmp = mac.length - index; + index = mac.length; + return tmp; + } + else + { + System.arraycopy(mac, index, b, off, len - index); + index += len; + return len; + } + } + return -1; + } +} + diff --git a/pkix/src/main/java/org/bouncycastle/cms/KEKRecipientInformation.java b/pkix/src/main/java/org/bouncycastle/cms/KEKRecipientInformation.java index 62c6529442..151e8a70ac 100644 --- a/pkix/src/main/java/org/bouncycastle/cms/KEKRecipientInformation.java +++ b/pkix/src/main/java/org/bouncycastle/cms/KEKRecipientInformation.java @@ -18,10 +18,9 @@ public class KEKRecipientInformation KEKRecipientInformation( KEKRecipientInfo info, AlgorithmIdentifier messageAlgorithm, - CMSSecureReadable secureReadable, - AuthAttributesProvider additionalData) + CMSSecureReadable secureReadable) { - super(info.getKeyEncryptionAlgorithm(), messageAlgorithm, secureReadable, additionalData); + super(info.getKeyEncryptionAlgorithm(), messageAlgorithm, secureReadable); this.info = info; diff --git a/pkix/src/main/java/org/bouncycastle/cms/KEMRecipientInformation.java b/pkix/src/main/java/org/bouncycastle/cms/KEMRecipientInformation.java index 76ad91dd7c..8a36dc8928 100644 --- a/pkix/src/main/java/org/bouncycastle/cms/KEMRecipientInformation.java +++ b/pkix/src/main/java/org/bouncycastle/cms/KEMRecipientInformation.java @@ -14,10 +14,9 @@ public class KEMRecipientInformation KEMRecipientInformation( KEMRecipientInfo info, AlgorithmIdentifier messageAlgorithm, - CMSSecureReadable secureReadable, - AuthAttributesProvider additionalData) + CMSSecureReadable secureReadable) { - super(info.getKem(), messageAlgorithm, secureReadable, additionalData); + super(info.getKem(), messageAlgorithm, secureReadable); this.info = info; diff --git a/pkix/src/main/java/org/bouncycastle/cms/KeyAgreeRecipientInformation.java b/pkix/src/main/java/org/bouncycastle/cms/KeyAgreeRecipientInformation.java index fc1580dfc1..ab3431f555 100644 --- a/pkix/src/main/java/org/bouncycastle/cms/KeyAgreeRecipientInformation.java +++ b/pkix/src/main/java/org/bouncycastle/cms/KeyAgreeRecipientInformation.java @@ -28,7 +28,7 @@ public class KeyAgreeRecipientInformation private ASN1OctetString encryptedKey; static void readRecipientInfo(List infos, KeyAgreeRecipientInfo info, - AlgorithmIdentifier messageAlgorithm, CMSSecureReadable secureReadable, AuthAttributesProvider additionalData) + AlgorithmIdentifier messageAlgorithm, CMSSecureReadable secureReadable) { ASN1Sequence s = info.getRecipientEncryptedKeys(); @@ -56,7 +56,7 @@ static void readRecipientInfo(List infos, KeyAgreeRecipientInfo info, } infos.add(new KeyAgreeRecipientInformation(info, rid, id.getEncryptedKey(), messageAlgorithm, - secureReadable, additionalData)); + secureReadable)); } } @@ -65,10 +65,9 @@ static void readRecipientInfo(List infos, KeyAgreeRecipientInfo info, RecipientId rid, ASN1OctetString encryptedKey, AlgorithmIdentifier messageAlgorithm, - CMSSecureReadable secureReadable, - AuthAttributesProvider additionalData) + CMSSecureReadable secureReadable) { - super(info.getKeyEncryptionAlgorithm(), messageAlgorithm, secureReadable, additionalData); + super(info.getKeyEncryptionAlgorithm(), messageAlgorithm, secureReadable); this.info = info; this.rid = rid; diff --git a/pkix/src/main/java/org/bouncycastle/cms/KeyTransRecipientInformation.java b/pkix/src/main/java/org/bouncycastle/cms/KeyTransRecipientInformation.java index d59f4b3e8b..649f1f21c8 100644 --- a/pkix/src/main/java/org/bouncycastle/cms/KeyTransRecipientInformation.java +++ b/pkix/src/main/java/org/bouncycastle/cms/KeyTransRecipientInformation.java @@ -19,10 +19,9 @@ public class KeyTransRecipientInformation KeyTransRecipientInformation( KeyTransRecipientInfo info, AlgorithmIdentifier messageAlgorithm, - CMSSecureReadable secureReadable, - AuthAttributesProvider additionalData) + CMSSecureReadable secureReadable) { - super(info.getKeyEncryptionAlgorithm(), messageAlgorithm, secureReadable, additionalData); + super(info.getKeyEncryptionAlgorithm(), messageAlgorithm, secureReadable); this.info = info; diff --git a/pkix/src/main/java/org/bouncycastle/cms/MACProvider.java b/pkix/src/main/java/org/bouncycastle/cms/MACProvider.java new file mode 100644 index 0000000000..75bafe1ad0 --- /dev/null +++ b/pkix/src/main/java/org/bouncycastle/cms/MACProvider.java @@ -0,0 +1,11 @@ +package org.bouncycastle.cms; + +import java.io.IOException; + +interface MACProvider +{ + byte[] getMAC(); + + void init() throws IOException; +} + diff --git a/pkix/src/main/java/org/bouncycastle/cms/PasswordRecipientInformation.java b/pkix/src/main/java/org/bouncycastle/cms/PasswordRecipientInformation.java index a12d8a7ccc..b0e29899be 100644 --- a/pkix/src/main/java/org/bouncycastle/cms/PasswordRecipientInformation.java +++ b/pkix/src/main/java/org/bouncycastle/cms/PasswordRecipientInformation.java @@ -37,10 +37,9 @@ public class PasswordRecipientInformation PasswordRecipientInformation( PasswordRecipientInfo info, AlgorithmIdentifier messageAlgorithm, - CMSSecureReadable secureReadable, - AuthAttributesProvider additionalData) + CMSSecureReadable secureReadable) { - super(info.getKeyEncryptionAlgorithm(), messageAlgorithm, secureReadable, additionalData); + super(info.getKeyEncryptionAlgorithm(), messageAlgorithm, secureReadable); this.info = info; this.rid = new PasswordRecipientId(); diff --git a/pkix/src/main/java/org/bouncycastle/cms/RecipientInformation.java b/pkix/src/main/java/org/bouncycastle/cms/RecipientInformation.java index 888dfb3417..fac620cab5 100644 --- a/pkix/src/main/java/org/bouncycastle/cms/RecipientInformation.java +++ b/pkix/src/main/java/org/bouncycastle/cms/RecipientInformation.java @@ -3,7 +3,6 @@ import java.io.ByteArrayInputStream; import java.io.IOException; -import org.bouncycastle.asn1.ASN1Encodable; import org.bouncycastle.asn1.ASN1Encoding; import org.bouncycastle.asn1.ASN1ObjectIdentifier; import org.bouncycastle.asn1.x509.AlgorithmIdentifier; @@ -12,25 +11,20 @@ public abstract class RecipientInformation { protected RecipientId rid; - protected AlgorithmIdentifier keyEncAlg; - protected AlgorithmIdentifier messageAlgorithm; - protected CMSSecureReadable secureReadable; - - private AuthAttributesProvider additionalData; - + protected AlgorithmIdentifier keyEncAlg; + protected AlgorithmIdentifier messageAlgorithm; + protected CMSSecureReadable secureReadable; private byte[] resultMac; - private RecipientOperator operator; + private RecipientOperator operator; RecipientInformation( AlgorithmIdentifier keyEncAlg, AlgorithmIdentifier messageAlgorithm, - CMSSecureReadable secureReadable, - AuthAttributesProvider additionalData) + CMSSecureReadable secureReadable) { this.keyEncAlg = keyEncAlg; this.messageAlgorithm = messageAlgorithm; this.secureReadable = secureReadable; - this.additionalData = additionalData; } public RecipientId getRID() @@ -38,18 +32,6 @@ public RecipientId getRID() return rid; } - private byte[] encodeObj( - ASN1Encodable obj) - throws IOException - { - if (obj != null) - { - return obj.toASN1Primitive().getEncoded(); - } - - return null; - } - /** * Return the key encryption algorithm details for the key in this recipient. * @@ -80,7 +62,7 @@ public byte[] getKeyEncryptionAlgParams() { try { - return encodeObj(keyEncAlg.getParameters()); + return CMSUtils.encodeObj(keyEncAlg.getParameters()); } catch (Exception e) { @@ -100,7 +82,6 @@ public byte[] getContentDigest() { return ((CMSEnvelopedHelper.CMSDigestAuthenticatedSecureReadable)secureReadable).getDigest(); } - return null; } @@ -108,29 +89,25 @@ public byte[] getContentDigest() * Return the MAC calculated for the recipient. Note: this call is only meaningful once all * the content has been read. * - * @return byte array containing the mac. + * @return byte array containing the mac. */ public byte[] getMac() { if (resultMac == null) { - if (operator.isMacBased()) + if (operator.isMacBased() && secureReadable.hasAdditionalData()) { - if (additionalData != null) + try { - try - { - Streams.drain(operator.getInputStream(new ByteArrayInputStream(additionalData.getAuthAttributes().getEncoded(ASN1Encoding.DER)))); - } - catch (IOException e) - { - throw new IllegalStateException("unable to drain input: " + e.getMessage()); - } + Streams.drain(operator.getInputStream(new ByteArrayInputStream(secureReadable.getAuthAttrSet().getEncoded(ASN1Encoding.DER)))); + } + catch (IOException e) + { + throw new IllegalStateException("unable to drain input: " + e.getMessage()); } - resultMac = operator.getMac(); } + resultMac = operator.getMac(); } - return resultMac; } @@ -139,7 +116,7 @@ public byte[] getMac() * encryption/MAC key using the passed in Recipient. * * @param recipient recipient object to use to recover content encryption key - * @return the content inside the EnvelopedData this RecipientInformation is associated with. + * @return the content inside the EnvelopedData this RecipientInformation is associated with. * @throws CMSException if the content-encryption/MAC key cannot be recovered. */ public byte[] getContent( @@ -171,7 +148,7 @@ public ASN1ObjectIdentifier getContentType() * encryption/MAC key using the passed in Recipient. * * @param recipient recipient object to use to recover content encryption key - * @return the content inside the EnvelopedData this RecipientInformation is associated with. + * @return the content inside the EnvelopedData this RecipientInformation is associated with. * @throws CMSException if the content-encryption/MAC key cannot be recovered. */ public CMSTypedStream getContentStream(Recipient recipient) @@ -179,19 +156,13 @@ public CMSTypedStream getContentStream(Recipient recipient) { operator = getRecipientOperator(recipient); - if (additionalData != null) + if (operator.isAEADBased()) { - if (additionalData.isAead()) - { - // TODO: this needs to be done after reading the encrypted data - operator.getAADStream().write(additionalData.getAuthAttributes().getEncoded(ASN1Encoding.DER)); - - return new CMSTypedStream(secureReadable.getContentType(), operator.getInputStream(secureReadable.getInputStream())); - } - else - { - return new CMSTypedStream(secureReadable.getContentType(), secureReadable.getInputStream()); - } + ((CMSSecureReadableWithAAD)secureReadable).setAADStream(operator.getAADStream()); + } + else if (secureReadable.hasAdditionalData()) + { + return new CMSTypedStream(secureReadable.getContentType(), secureReadable.getInputStream()); } return new CMSTypedStream(secureReadable.getContentType(), operator.getInputStream(secureReadable.getInputStream())); diff --git a/pkix/src/main/java/org/bouncycastle/cms/RecipientOperator.java b/pkix/src/main/java/org/bouncycastle/cms/RecipientOperator.java index 407d5bceb6..3c51327f42 100644 --- a/pkix/src/main/java/org/bouncycastle/cms/RecipientOperator.java +++ b/pkix/src/main/java/org/bouncycastle/cms/RecipientOperator.java @@ -51,6 +51,14 @@ public boolean isMacBased() public byte[] getMac() { - return ((MacCalculator)operator).getMac(); + if (operator instanceof MacCalculator) + { + return ((MacCalculator)operator).getMac(); + } + else if (operator instanceof InputAEADDecryptor) + { + return ((InputAEADDecryptor)operator).getMAC(); + } + return null; } } diff --git a/pkix/src/main/java/org/bouncycastle/cms/SignerInformation.java b/pkix/src/main/java/org/bouncycastle/cms/SignerInformation.java index 06a444d613..b2451b5262 100644 --- a/pkix/src/main/java/org/bouncycastle/cms/SignerInformation.java +++ b/pkix/src/main/java/org/bouncycastle/cms/SignerInformation.java @@ -7,7 +7,6 @@ import java.util.Iterator; import java.util.List; -import org.bouncycastle.asn1.ASN1Encodable; import org.bouncycastle.asn1.ASN1EncodableVector; import org.bouncycastle.asn1.ASN1Encoding; import org.bouncycastle.asn1.ASN1ObjectIdentifier; @@ -140,18 +139,6 @@ public ASN1ObjectIdentifier getContentType() return this.contentType; } - private byte[] encodeObj( - ASN1Encodable obj) - throws IOException - { - if (obj != null) - { - return obj.toASN1Primitive().getEncoded(); - } - - return null; - } - public SignerId getSID() { return sid; @@ -185,7 +172,7 @@ public byte[] getDigestAlgParams() { try { - return encodeObj(digestAlgorithm.getParameters()); + return CMSUtils.encodeObj(digestAlgorithm.getParameters()); } catch (Exception e) { @@ -222,7 +209,7 @@ public byte[] getEncryptionAlgParams() { try { - return encodeObj(encryptionAlgorithm.getParameters()); + return CMSUtils.encodeObj(encryptionAlgorithm.getParameters()); } catch (Exception e) { diff --git a/pkix/src/main/java/org/bouncycastle/cms/jcajce/JceKeyTransAuthEnvelopedRecipient.java b/pkix/src/main/java/org/bouncycastle/cms/jcajce/JceKeyTransAuthEnvelopedRecipient.java index ef76148c9c..c697ca83f5 100644 --- a/pkix/src/main/java/org/bouncycastle/cms/jcajce/JceKeyTransAuthEnvelopedRecipient.java +++ b/pkix/src/main/java/org/bouncycastle/cms/jcajce/JceKeyTransAuthEnvelopedRecipient.java @@ -10,6 +10,7 @@ import org.bouncycastle.asn1.x509.AlgorithmIdentifier; import org.bouncycastle.cms.CMSException; +import org.bouncycastle.cms.InputStreamWithMAC; import org.bouncycastle.cms.RecipientOperator; import org.bouncycastle.jcajce.io.CipherInputStream; import org.bouncycastle.operator.InputAEADDecryptor; @@ -31,6 +32,8 @@ public RecipientOperator getRecipientOperator(AlgorithmIdentifier keyEncryptionA return new RecipientOperator(new InputAEADDecryptor() { + private InputStream inputStream; + public AlgorithmIdentifier getAlgorithmIdentifier() { return contentEncryptionAlgorithm; @@ -38,6 +41,7 @@ public AlgorithmIdentifier getAlgorithmIdentifier() public InputStream getInputStream(InputStream dataIn) { + inputStream = dataIn; return new CipherInputStream(dataIn, dataCipher); } @@ -48,8 +52,11 @@ public OutputStream getAADStream() public byte[] getMAC() { - // TODO - return new byte[0]; + if (inputStream instanceof InputStreamWithMAC) + { + return ((InputStreamWithMAC)inputStream).getMAC(); + } + return null; } }); } @@ -64,7 +71,7 @@ public AADStream(Cipher cipher) { this.cipher = cipher; } - + public void write(byte[] buf, int off, int len) throws IOException { diff --git a/pkix/src/main/java/org/bouncycastle/operator/InputAEADDecryptor.java b/pkix/src/main/java/org/bouncycastle/operator/InputAEADDecryptor.java index 88adef4084..976d37859d 100644 --- a/pkix/src/main/java/org/bouncycastle/operator/InputAEADDecryptor.java +++ b/pkix/src/main/java/org/bouncycastle/operator/InputAEADDecryptor.java @@ -1,5 +1,6 @@ package org.bouncycastle.operator; + /** * Base interface for an input consuming AEAD Decryptor supporting associated text. */ diff --git a/pkix/src/test/java/org/bouncycastle/cms/test/AllTests.java b/pkix/src/test/java/org/bouncycastle/cms/test/AllTests.java index f2160badf5..8cb1b712bc 100644 --- a/pkix/src/test/java/org/bouncycastle/cms/test/AllTests.java +++ b/pkix/src/test/java/org/bouncycastle/cms/test/AllTests.java @@ -37,6 +37,8 @@ public static Test suite() suite.addTest(BcEnvelopedDataTest.suite()); suite.addTest(BcSignedDataTest.suite()); + suite.addTest(CMSAuthEnvelopedDataStreamGeneratorTest.suite()); + suite.addTest(InputStreamWithMACTest.suite()); try { diff --git a/pkix/src/test/java/org/bouncycastle/cms/test/AuthEnvelopedDataTest.java b/pkix/src/test/java/org/bouncycastle/cms/test/AuthEnvelopedDataTest.java index 60e0062831..6d81c93fb6 100644 --- a/pkix/src/test/java/org/bouncycastle/cms/test/AuthEnvelopedDataTest.java +++ b/pkix/src/test/java/org/bouncycastle/cms/test/AuthEnvelopedDataTest.java @@ -248,7 +248,7 @@ public AttributeTable getAttributes(Map parameters) RecipientInformation recipient = (RecipientInformation)recipients.getRecipients().iterator().next(); byte[] recData = recipient.getContent(new JceKeyTransAuthEnvelopedRecipient(_reciKP.getPrivate()).setProvider(BC)); - + assertTrue(java.util.Arrays.equals(authData.getMac(), recipient.getMac())); assertEquals("Hello, world!", Strings.fromByteArray(recData)); } @@ -293,7 +293,7 @@ public AttributeTable getAttributes(Map parameters) if (System.getProperty("java.version").indexOf("1.5.") < 0) { byte[] recData = recipient.getContent(new JceKeyTransAuthEnvelopedRecipient(_reciKP.getPrivate()).setProvider(BC)); - + assertTrue(java.util.Arrays.equals(authData.getMac(), recipient.getMac())); assertEquals("Hello, world!", Strings.fromByteArray(recData)); } } diff --git a/pkix/src/test/java/org/bouncycastle/cms/test/CMSAuthEnvelopedDataStreamGeneratorTest.java b/pkix/src/test/java/org/bouncycastle/cms/test/CMSAuthEnvelopedDataStreamGeneratorTest.java new file mode 100644 index 0000000000..1a73d5fad3 --- /dev/null +++ b/pkix/src/test/java/org/bouncycastle/cms/test/CMSAuthEnvelopedDataStreamGeneratorTest.java @@ -0,0 +1,340 @@ +package org.bouncycastle.cms.test; + +import java.io.ByteArrayOutputStream; +import java.io.OutputStream; +import java.security.KeyPair; +import java.security.cert.X509Certificate; +import java.util.Arrays; +import java.util.Collection; +import java.util.Date; +import java.util.Hashtable; +import java.util.Iterator; +import java.util.Map; + +import junit.framework.Test; +import junit.framework.TestCase; +import junit.framework.TestSuite; +import org.bouncycastle.asn1.ASN1ObjectIdentifier; +import org.bouncycastle.asn1.DERSet; +import org.bouncycastle.asn1.cms.Attribute; +import org.bouncycastle.asn1.cms.AttributeTable; +import org.bouncycastle.asn1.cms.CMSAttributes; +import org.bouncycastle.asn1.cms.GCMParameters; +import org.bouncycastle.asn1.cms.Time; +import org.bouncycastle.cms.CMSAlgorithm; +import org.bouncycastle.cms.CMSAttributeTableGenerationException; +import org.bouncycastle.cms.CMSAttributeTableGenerator; +import org.bouncycastle.cms.CMSAuthEnvelopedDataStreamGenerator; +import org.bouncycastle.cms.CMSAuthEnvelopedDataParser; +import org.bouncycastle.cms.CMSTypedStream; +import org.bouncycastle.cms.RecipientInformation; +import org.bouncycastle.cms.RecipientInformationStore; +import org.bouncycastle.cms.jcajce.JceCMSContentEncryptorBuilder; +import org.bouncycastle.cms.jcajce.JceKeyTransAuthEnvelopedRecipient; +import org.bouncycastle.cms.jcajce.JceKeyTransRecipientInfoGenerator; +import org.bouncycastle.jce.provider.BouncyCastleProvider; +import org.bouncycastle.operator.OutputAEADEncryptor; +import org.bouncycastle.operator.OutputEncryptor; +import org.bouncycastle.util.Strings; + +public class CMSAuthEnvelopedDataStreamGeneratorTest + extends TestCase +{ + public static void main(String[] args) + throws Exception + { + CMSAuthEnvelopedDataStreamGeneratorTest test = new CMSAuthEnvelopedDataStreamGeneratorTest(); + test.setUp(); + test.testGCMCCM(); + test.testNoAuthAttributes(); + test.testNoAttributes(); + + } + + private static final String BC = BouncyCastleProvider.PROVIDER_NAME; + + private static final int BUFFER_SIZE = 4000; + private static String _signDN; + private static KeyPair _signKP; + private static X509Certificate _signCert; + + private static String _origDN; + private static KeyPair _origKP; + private static X509Certificate _origCert; + + private static String _reciDN; + private static KeyPair _reciKP; + private static X509Certificate _reciCert; + + private static KeyPair _origEcKP; + private static KeyPair _reciEcKP; + private static X509Certificate _reciEcCert; + + private static boolean _initialised = false; + + private static void init() + throws Exception + { + if (!_initialised) + { + _initialised = true; + + _signDN = "O=Bouncy Castle, C=AU"; + _signKP = CMSTestUtil.makeKeyPair(); + _signCert = CMSTestUtil.makeCertificate(_signKP, _signDN, _signKP, _signDN); + + _origDN = "CN=Bob, OU=Sales, O=Bouncy Castle, C=AU"; + _origKP = CMSTestUtil.makeKeyPair(); + _origCert = CMSTestUtil.makeCertificate(_origKP, _origDN, _signKP, _signDN); + + _reciDN = "CN=Doug, OU=Sales, O=Bouncy Castle, C=AU"; + _reciKP = CMSTestUtil.makeKeyPair(); + _reciCert = CMSTestUtil.makeCertificate(_reciKP, _reciDN, _signKP, _signDN); + + _origEcKP = CMSTestUtil.makeEcDsaKeyPair(); + _reciEcKP = CMSTestUtil.makeEcDsaKeyPair(); + _reciEcCert = CMSTestUtil.makeCertificate(_reciEcKP, _reciDN, _signKP, _signDN); + } + } + + public static Test suite() + throws Exception + { + init(); + + return new CMSTestSetup(new TestSuite(CMSAuthEnvelopedDataStreamGeneratorTest.class)); + } + + public void setUp() + throws Exception + { + init(); + } + + public void testGCMCCM() + throws Exception + { + GCMCCMtest(CMSAlgorithm.AES128_GCM, false); + GCMCCMtest(CMSAlgorithm.AES192_GCM, false); + GCMCCMtest(CMSAlgorithm.AES256_GCM, false); + GCMCCMtest(CMSAlgorithm.AES128_CCM, false); + GCMCCMtest(CMSAlgorithm.AES192_CCM, false); + GCMCCMtest(CMSAlgorithm.AES256_CCM, false); + + GCMCCMtest(CMSAlgorithm.AES128_GCM, true); + GCMCCMtest(CMSAlgorithm.AES192_GCM, true); + GCMCCMtest(CMSAlgorithm.AES256_GCM, true); + GCMCCMtest(CMSAlgorithm.AES128_CCM, true); + GCMCCMtest(CMSAlgorithm.AES192_CCM, true); + GCMCCMtest(CMSAlgorithm.AES256_CCM, true); + } + + public void GCMCCMtest(ASN1ObjectIdentifier oid, boolean berEncodeRecipientSet) + throws Exception + { + if (!CMSTestUtil.isAeadAvailable()) + { + return; + } + byte[] message = Strings.toByteArray("Hello, world!"); + + OutputEncryptor candidate = new JceCMSContentEncryptorBuilder(oid).setProvider(BC).build(); + + assertEquals(oid, candidate.getAlgorithmIdentifier().getAlgorithm()); + assertNotNull(GCMParameters.getInstance(candidate.getAlgorithmIdentifier().getParameters())); + + assertTrue(candidate instanceof OutputAEADEncryptor); + + CMSAuthEnvelopedDataStreamGenerator authGen = new CMSAuthEnvelopedDataStreamGenerator(); + + authGen.addRecipientInfoGenerator(new JceKeyTransRecipientInfoGenerator(_reciCert)); + authGen.setBEREncodeRecipients(berEncodeRecipientSet); + authGen.setAuthenticatedAttributeGenerator(new CMSAttributeTableGenerator() + { + public AttributeTable getAttributes(Map parameters) + throws CMSAttributeTableGenerationException + { + Hashtable attrs = new Hashtable(); + Attribute testAttr = new Attribute(CMSAttributes.signingTime, + new DERSet(new Time(new Date()))); + attrs.put(testAttr.getAttrType(), testAttr); + return new AttributeTable(attrs); + } + }); + + authGen.setUnauthenticatedAttributeGenerator(new CMSAttributeTableGenerator() + { + public AttributeTable getAttributes(Map parameters) + throws CMSAttributeTableGenerationException + { + Hashtable attrs = new Hashtable(); + Attribute testAttr = new Attribute(CMSAttributes.signingTime, + new DERSet(new Time(new Date()))); + attrs.put(testAttr.getAttrType(), testAttr); + return new AttributeTable(attrs); + } + }); + + ByteArrayOutputStream bOut = new ByteArrayOutputStream(); + + OutputStream out = authGen.open(bOut, ( + OutputAEADEncryptor)new JceCMSContentEncryptorBuilder(oid).setProvider(BC).build()); + out.write(message); + + out.close(); + + CMSAuthEnvelopedDataParser ep = new CMSAuthEnvelopedDataParser(bOut.toByteArray()); + + RecipientInformationStore recipients = ep.getRecipientInfos(); + + assertEquals(ep.getEncryptionAlgOID().getAlgorithm(), oid); + assertEquals(ep.getEncAlgOID(), oid.getId()); + assertNotNull(ep.getEncAlgParams()); + + Collection c = recipients.getRecipients(); + + Iterator it = c.iterator(); + + while (it.hasNext()) + { + RecipientInformation recipient = (RecipientInformation)it.next(); + + assertEquals(recipient.getKeyEncryptionAlgOID(), "1.2.840.113549.1.1.1"); + + CMSTypedStream recData = recipient.getContentStream(new JceKeyTransAuthEnvelopedRecipient(_reciKP.getPrivate()).setProvider(BC)); + + assertEquals(true, Arrays.equals(message, CMSTestUtil.streamToByteArray(recData.getContentStream()))); + assertTrue(Arrays.equals(ep.getMac(), recipient.getMac())); + //assertEquals(1, ep.getAuthAttrs().size()); + assertEquals(1, ep.getUnauthAttrs().size()); + } + ep.close(); + } + + public void testNoAuthAttributes() + throws Exception + { + ASN1ObjectIdentifier oid = CMSAlgorithm.AES128_GCM; + if (!CMSTestUtil.isAeadAvailable()) + { + return; + } + byte[] message = Strings.toByteArray("Hello, world!"); + + OutputEncryptor candidate = new JceCMSContentEncryptorBuilder(oid).setProvider(BC).build(); + + assertEquals(oid, candidate.getAlgorithmIdentifier().getAlgorithm()); + assertNotNull(GCMParameters.getInstance(candidate.getAlgorithmIdentifier().getParameters())); + + assertTrue(candidate instanceof OutputAEADEncryptor); + + CMSAuthEnvelopedDataStreamGenerator authGen = new CMSAuthEnvelopedDataStreamGenerator(); + + authGen.addRecipientInfoGenerator(new JceKeyTransRecipientInfoGenerator(_reciCert)); + + authGen.setUnauthenticatedAttributeGenerator(new CMSAttributeTableGenerator() + { + public AttributeTable getAttributes(Map parameters) + throws CMSAttributeTableGenerationException + { + Hashtable attrs = new Hashtable(); + Attribute testAttr = new Attribute(CMSAttributes.signingTime, + new DERSet(new Time(new Date()))); + attrs.put(testAttr.getAttrType(), testAttr); + return new AttributeTable(attrs); + } + }); + + ByteArrayOutputStream bOut = new ByteArrayOutputStream(); + + OutputStream out = authGen.open(bOut, ( + OutputAEADEncryptor)new JceCMSContentEncryptorBuilder(oid).setProvider(BC).build()); + out.write(message); + + out.close(); + + CMSAuthEnvelopedDataParser ep = new CMSAuthEnvelopedDataParser(bOut.toByteArray()); + + //System.err.println(ASN1Dump.dumpAsString(ASN1Primitive.fromByteArray(bOut.toByteArray()))); + RecipientInformationStore recipients = ep.getRecipientInfos(); + + assertEquals(ep.getEncryptionAlgOID().getAlgorithm(), oid); + assertEquals(ep.getEncAlgOID(), oid.getId()); + assertNotNull(ep.getEncAlgParams()); + + Collection c = recipients.getRecipients(); + + Iterator it = c.iterator(); + + while (it.hasNext()) + { + RecipientInformation recipient = (RecipientInformation)it.next(); + + assertEquals(recipient.getKeyEncryptionAlgOID(), "1.2.840.113549.1.1.1"); + + CMSTypedStream recData = recipient.getContentStream(new JceKeyTransAuthEnvelopedRecipient(_reciKP.getPrivate()).setProvider(BC)); + + assertEquals(true, Arrays.equals(message, CMSTestUtil.streamToByteArray(recData.getContentStream()))); + assertTrue(Arrays.equals(ep.getMac(), recipient.getMac())); + assertNull(ep.getAuthAttrs()); + assertEquals(1, ep.getUnauthAttrs().size()); + } + ep.close(); + } + + public void testNoAttributes() + throws Exception + { + ASN1ObjectIdentifier oid = CMSAlgorithm.AES128_GCM; + if (!CMSTestUtil.isAeadAvailable()) + { + return; + } + byte[] message = Strings.toByteArray("Hello, world!"); + + OutputEncryptor candidate = new JceCMSContentEncryptorBuilder(oid).setProvider(BC).build(); + + assertEquals(oid, candidate.getAlgorithmIdentifier().getAlgorithm()); + assertNotNull(GCMParameters.getInstance(candidate.getAlgorithmIdentifier().getParameters())); + + assertTrue(candidate instanceof OutputAEADEncryptor); + + CMSAuthEnvelopedDataStreamGenerator authGen = new CMSAuthEnvelopedDataStreamGenerator(); + + authGen.addRecipientInfoGenerator(new JceKeyTransRecipientInfoGenerator(_reciCert)); + + ByteArrayOutputStream bOut = new ByteArrayOutputStream(); + + OutputStream out = authGen.open(bOut, ( + OutputAEADEncryptor)new JceCMSContentEncryptorBuilder(oid).setProvider(BC).build()); + out.write(message); + + out.close(); + + CMSAuthEnvelopedDataParser ep = new CMSAuthEnvelopedDataParser(bOut.toByteArray()); + + //System.err.println(ASN1Dump.dumpAsString(ASN1Primitive.fromByteArray(bOut.toByteArray()))); + RecipientInformationStore recipients = ep.getRecipientInfos(); + + assertEquals(ep.getEncryptionAlgOID().getAlgorithm(), oid); + assertEquals(ep.getEncAlgOID(), oid.getId()); + assertNotNull(ep.getEncAlgParams()); + + Collection c = recipients.getRecipients(); + + Iterator it = c.iterator(); + + while (it.hasNext()) + { + RecipientInformation recipient = (RecipientInformation)it.next(); + + assertEquals(recipient.getKeyEncryptionAlgOID(), "1.2.840.113549.1.1.1"); + + CMSTypedStream recData = recipient.getContentStream(new JceKeyTransAuthEnvelopedRecipient(_reciKP.getPrivate()).setProvider(BC)); + + assertEquals(true, Arrays.equals(message, CMSTestUtil.streamToByteArray(recData.getContentStream()))); + assertTrue(Arrays.equals(ep.getMac(), recipient.getMac())); + } + ep.close(); + } +} diff --git a/pkix/src/test/java/org/bouncycastle/cms/test/InputStreamWithMACTest.java b/pkix/src/test/java/org/bouncycastle/cms/test/InputStreamWithMACTest.java new file mode 100644 index 0000000000..d5456b8963 --- /dev/null +++ b/pkix/src/test/java/org/bouncycastle/cms/test/InputStreamWithMACTest.java @@ -0,0 +1,62 @@ +package org.bouncycastle.cms.test; + +import java.io.ByteArrayInputStream; +import java.io.IOException; + +import junit.framework.Test; +import junit.framework.TestCase; +import junit.framework.TestSuite; +import org.bouncycastle.cms.InputStreamWithMAC; + +public class InputStreamWithMACTest + extends TestCase +{ + public static void main(String[] args) + throws IOException + { + InputStreamWithMACTest test = new InputStreamWithMACTest(); + // test.testRead(); + test.testReadBlock(); + } + + public static Test suite() + throws Exception + { + return new CMSTestSetup(new TestSuite(InputStreamWithMACTest.class)); + } + +// public void testRead() +// throws IOException +// { +// byte[] array = new byte[Integer.MAX_VALUE - 16]; +// InputStreamWithMAC inputStream = new InputStreamWithMAC(new ByteArrayInputStream(array), new byte[16]); +// while (inputStream.read() != -1) ; +// } + + public void testReadBlock() + throws IOException + { + byte[] array = new byte[32]; + byte[] mac = new byte[]{ + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1}; + InputStreamWithMAC inputStream = new InputStreamWithMAC(new ByteArrayInputStream(array), mac); + try + { + inputStream.getMAC(); + } + catch (IllegalStateException e) + { + assertEquals("input stream not fully processed", e.getMessage()); + } + assertEquals(32, inputStream.read(new byte[46], 0, 46)); + assertEquals(1, inputStream.read(new byte[1], 0, 1)); + assertEquals(1, inputStream.read(new byte[1], 0, 1)); + assertEquals(14, inputStream.read(new byte[17], 0, 17)); + inputStream = new InputStreamWithMAC(new ByteArrayInputStream(array), mac); + assertEquals(32, inputStream.read(new byte[46], 0, 46)); + assertEquals(16, inputStream.read(new byte[17], 0, 17)); + assertEquals(-1, inputStream.read(new byte[17], 0, 17)); + assertEquals(-1, inputStream.read()); + } +} diff --git a/pkix/src/test/java/org/bouncycastle/cms/test/NewEnvelopedDataStreamTest.java b/pkix/src/test/java/org/bouncycastle/cms/test/NewEnvelopedDataStreamTest.java index 8649b0286c..535bbcc556 100644 --- a/pkix/src/test/java/org/bouncycastle/cms/test/NewEnvelopedDataStreamTest.java +++ b/pkix/src/test/java/org/bouncycastle/cms/test/NewEnvelopedDataStreamTest.java @@ -30,6 +30,7 @@ import org.bouncycastle.asn1.x500.X500Name; import org.bouncycastle.cert.X509CertificateHolder; import org.bouncycastle.cms.CMSAlgorithm; +import org.bouncycastle.cms.CMSAuthEnvelopedDataStreamGenerator; import org.bouncycastle.cms.CMSEnvelopedDataGenerator; import org.bouncycastle.cms.CMSEnvelopedDataParser; import org.bouncycastle.cms.CMSEnvelopedDataStreamGenerator; @@ -50,33 +51,35 @@ import org.bouncycastle.cms.jcajce.JceKeyTransEnvelopedRecipient; import org.bouncycastle.cms.jcajce.JceKeyTransRecipientInfoGenerator; import org.bouncycastle.jce.provider.BouncyCastleProvider; +import org.bouncycastle.operator.OutputAEADEncryptor; import org.bouncycastle.util.encoders.Base64; import org.bouncycastle.util.encoders.Hex; public class NewEnvelopedDataStreamTest extends TestCase { + private static final String BC = BouncyCastleProvider.PROVIDER_NAME; private static final int BUFFER_SIZE = 4000; - private static String _signDN; - private static KeyPair _signKP; + private static String _signDN; + private static KeyPair _signKP; private static X509Certificate _signCert; - private static String _origDN; - private static KeyPair _origKP; + private static String _origDN; + private static KeyPair _origKP; private static X509Certificate _origCert; - private static String _reciDN; - private static KeyPair _reciKP; + private static String _reciDN; + private static KeyPair _reciKP; private static X509Certificate _reciCert; - private static KeyPair _origEcKP; - private static KeyPair _reciEcKP; + private static KeyPair _origEcKP; + private static KeyPair _reciEcKP; private static X509Certificate _reciEcCert; - private static boolean _initialised = false; - + private static boolean _initialised = false; + public NewEnvelopedDataStreamTest() { } @@ -88,16 +91,16 @@ private static void init() { _initialised = true; - _signDN = "O=Bouncy Castle, C=AU"; - _signKP = CMSTestUtil.makeKeyPair(); + _signDN = "O=Bouncy Castle, C=AU"; + _signKP = CMSTestUtil.makeKeyPair(); _signCert = CMSTestUtil.makeCertificate(_signKP, _signDN, _signKP, _signDN); - _origDN = "CN=Bob, OU=Sales, O=Bouncy Castle, C=AU"; - _origKP = CMSTestUtil.makeKeyPair(); + _origDN = "CN=Bob, OU=Sales, O=Bouncy Castle, C=AU"; + _origKP = CMSTestUtil.makeKeyPair(); _origCert = CMSTestUtil.makeCertificate(_origKP, _origDN, _signKP, _signDN); - _reciDN = "CN=Doug, OU=Sales, O=Bouncy Castle, C=AU"; - _reciKP = CMSTestUtil.makeKeyPair(); + _reciDN = "CN=Doug, OU=Sales, O=Bouncy Castle, C=AU"; + _reciKP = CMSTestUtil.makeKeyPair(); _reciCert = CMSTestUtil.makeCertificate(_reciKP, _reciDN, _signKP, _signDN); _origEcKP = CMSTestUtil.makeEcDsaKeyPair(); @@ -115,50 +118,50 @@ public void setUp() public void testWorkingData() throws Exception { - byte[] keyData = Base64.decode( - "MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAKrAz/SQKrcQ" + - "nj9IxHIfKDbuXsMqUpI06s2gps6fp7RDNvtUDDMOciWGFhD45YSy8GO0mPx3" + - "Nkc7vKBqX4TLcqLUz7kXGOHGOwiPZoNF+9jBMPNROe/B0My0PkWg9tuq+nxN" + - "64oD47+JvDwrpNOS5wsYavXeAW8Anv9ZzHLU7KwZAgMBAAECgYA/fqdVt+5K" + - "WKGfwr1Z+oAHvSf7xtchiw/tGtosZ24DOCNP3fcTXUHQ9kVqVkNyzt9ZFCT3" + - "bJUAdBQ2SpfuV4DusVeQZVzcROKeA09nPkxBpTefWbSDQGhb+eZq9L8JDRSW" + - "HyYqs+MBoUpLw7GKtZiJkZyY6CsYkAnQ+uYVWq/TIQJBAP5zafO4HUV/w4KD" + - "VJi+ua+GYF1Sg1t/dYL1kXO9GP1p75YAmtm6LdnOCas7wj70/G1YlPGkOP0V" + - "GFzeG5KAmAUCQQCryvKU9nwWA+kypcQT9Yr1P4vGS0APYoBThnZq7jEPc5Cm" + - "ZI82yseSxSeea0+8KQbZ5mvh1p3qImDLEH/iNSQFAkAghS+tboKPN10NeSt+" + - "uiGRRWNbiggv0YJ7Uldcq3ZeLQPp7/naiekCRUsHD4Qr97OrZf7jQ1HlRqTu" + - "eZScjMLhAkBNUMZCQnhwFAyEzdPkQ7LpU1MdyEopYmRssuxijZao5JLqQAGw" + - "YCzXokGFa7hz72b09F4DQurJL/WuDlvvu4jdAkEAxwT9lylvfSfEQw4/qQgZ" + - "MFB26gqB6Gqs1pHIZCzdliKx5BO3VDeUGfXMI8yOkbXoWbYx5xPid/+N8R//" + - "+sxLBw=="); + byte[] keyData = Base64.decode( + "MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAKrAz/SQKrcQ" + + "nj9IxHIfKDbuXsMqUpI06s2gps6fp7RDNvtUDDMOciWGFhD45YSy8GO0mPx3" + + "Nkc7vKBqX4TLcqLUz7kXGOHGOwiPZoNF+9jBMPNROe/B0My0PkWg9tuq+nxN" + + "64oD47+JvDwrpNOS5wsYavXeAW8Anv9ZzHLU7KwZAgMBAAECgYA/fqdVt+5K" + + "WKGfwr1Z+oAHvSf7xtchiw/tGtosZ24DOCNP3fcTXUHQ9kVqVkNyzt9ZFCT3" + + "bJUAdBQ2SpfuV4DusVeQZVzcROKeA09nPkxBpTefWbSDQGhb+eZq9L8JDRSW" + + "HyYqs+MBoUpLw7GKtZiJkZyY6CsYkAnQ+uYVWq/TIQJBAP5zafO4HUV/w4KD" + + "VJi+ua+GYF1Sg1t/dYL1kXO9GP1p75YAmtm6LdnOCas7wj70/G1YlPGkOP0V" + + "GFzeG5KAmAUCQQCryvKU9nwWA+kypcQT9Yr1P4vGS0APYoBThnZq7jEPc5Cm" + + "ZI82yseSxSeea0+8KQbZ5mvh1p3qImDLEH/iNSQFAkAghS+tboKPN10NeSt+" + + "uiGRRWNbiggv0YJ7Uldcq3ZeLQPp7/naiekCRUsHD4Qr97OrZf7jQ1HlRqTu" + + "eZScjMLhAkBNUMZCQnhwFAyEzdPkQ7LpU1MdyEopYmRssuxijZao5JLqQAGw" + + "YCzXokGFa7hz72b09F4DQurJL/WuDlvvu4jdAkEAxwT9lylvfSfEQw4/qQgZ" + + "MFB26gqB6Gqs1pHIZCzdliKx5BO3VDeUGfXMI8yOkbXoWbYx5xPid/+N8R//" + + "+sxLBw=="); byte[] envData = Base64.decode( - "MIAGCSqGSIb3DQEHA6CAMIACAQAxgcQwgcECAQAwKjAlMRYwFAYDVQQKEw1C" + - "b3VuY3kgQ2FzdGxlMQswCQYDVQQGEwJBVQIBHjANBgkqhkiG9w0BAQEFAASB" + - "gDmnaDZ0vDJNlaUSYyEXsgbaUH+itNTjCOgv77QTX2ImXj+kTctM19PQF2I1" + - "0/NL0fjakvCgBTHKmk13a7jqB6cX3bysenHNrglHsgNGgeXQ7ggAq5fV/JQQ" + - "T7rSxEtuwpbuHQnoVUZahOHVKy/a0uLr9iIh1A3y+yZTZaG505ZJMIAGCSqG" + - "SIb3DQEHATAdBglghkgBZQMEAQIEENmkYNbDXiZxJWtq82qIRZKggAQgkOGr" + - "1JcTsADStez1eY4+rO4DtyBIyUYQ3pilnbirfPkAAAAAAAAAAAAA"); + "MIAGCSqGSIb3DQEHA6CAMIACAQAxgcQwgcECAQAwKjAlMRYwFAYDVQQKEw1C" + + "b3VuY3kgQ2FzdGxlMQswCQYDVQQGEwJBVQIBHjANBgkqhkiG9w0BAQEFAASB" + + "gDmnaDZ0vDJNlaUSYyEXsgbaUH+itNTjCOgv77QTX2ImXj+kTctM19PQF2I1" + + "0/NL0fjakvCgBTHKmk13a7jqB6cX3bysenHNrglHsgNGgeXQ7ggAq5fV/JQQ" + + "T7rSxEtuwpbuHQnoVUZahOHVKy/a0uLr9iIh1A3y+yZTZaG505ZJMIAGCSqG" + + "SIb3DQEHATAdBglghkgBZQMEAQIEENmkYNbDXiZxJWtq82qIRZKggAQgkOGr" + + "1JcTsADStez1eY4+rO4DtyBIyUYQ3pilnbirfPkAAAAAAAAAAAAA"); - CMSEnvelopedDataParser ep = new CMSEnvelopedDataParser(envData); + CMSEnvelopedDataParser ep = new CMSEnvelopedDataParser(envData); - RecipientInformationStore recipients = ep.getRecipientInfos(); + RecipientInformationStore recipients = ep.getRecipientInfos(); assertEquals(ep.getEncryptionAlgOID(), CMSEnvelopedDataGenerator.AES128_CBC); - Collection c = recipients.getRecipients(); - Iterator it = c.iterator(); + Collection c = recipients.getRecipients(); + Iterator it = c.iterator(); PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(keyData); - KeyFactory keyFact = KeyFactory.getInstance("RSA", BC); - PrivateKey priKey = keyFact.generatePrivate(keySpec); - byte[] data = Hex.decode("57616c6c6157616c6c6157617368696e67746f6e"); + KeyFactory keyFact = KeyFactory.getInstance("RSA", BC); + PrivateKey priKey = keyFact.generatePrivate(keySpec); + byte[] data = Hex.decode("57616c6c6157616c6c6157617368696e67746f6e"); while (it.hasNext()) { - RecipientInformation recipient = (RecipientInformation)it.next(); + RecipientInformation recipient = (RecipientInformation)it.next(); assertEquals(recipient.getKeyEncryptionAlgOID(), PKCSObjectIdentifiers.rsaEncryption.getId()); @@ -170,21 +173,21 @@ public void testWorkingData() private void verifyData( ByteArrayOutputStream encodedStream, - String expectedOid, - byte[] expectedData) + String expectedOid, + byte[] expectedData) throws Exception { - CMSEnvelopedDataParser ep = new CMSEnvelopedDataParser(encodedStream.toByteArray()); - RecipientInformationStore recipients = ep.getRecipientInfos(); + CMSEnvelopedDataParser ep = new CMSEnvelopedDataParser(encodedStream.toByteArray()); + RecipientInformationStore recipients = ep.getRecipientInfos(); assertEquals(ep.getEncryptionAlgOID(), expectedOid); - Collection c = recipients.getRecipients(); - Iterator it = c.iterator(); + Collection c = recipients.getRecipients(); + Iterator it = c.iterator(); while (it.hasNext()) { - RecipientInformation recipient = (RecipientInformation)it.next(); + RecipientInformation recipient = (RecipientInformation)it.next(); assertEquals(recipient.getKeyEncryptionAlgOID(), PKCSObjectIdentifiers.rsaEncryption.getId()); @@ -197,7 +200,7 @@ private void verifyData( public void testUnprotectedAttributes() throws Exception { - byte[] data = "WallaWallaWashington".getBytes(); + byte[] data = "WallaWallaWashington".getBytes(); CMSEnvelopedDataStreamGenerator edGen = new CMSEnvelopedDataStreamGenerator(); @@ -212,10 +215,10 @@ public void testUnprotectedAttributes() edGen.setUnprotectedAttributeGenerator(new SimpleAttributeTableGenerator(attrTable)); - ByteArrayOutputStream bOut = new ByteArrayOutputStream(); + ByteArrayOutputStream bOut = new ByteArrayOutputStream(); OutputStream out = edGen.open( - bOut, new JceCMSContentEncryptorBuilder(CMSAlgorithm.AES128_CBC).setProvider(BC).build()); + bOut, new JceCMSContentEncryptorBuilder(CMSAlgorithm.AES128_CBC).setProvider(BC).build()); out.write(data); @@ -223,17 +226,17 @@ public void testUnprotectedAttributes() CMSEnvelopedDataParser ed = new CMSEnvelopedDataParser(bOut.toByteArray()); - RecipientInformationStore recipients = ed.getRecipientInfos(); + RecipientInformationStore recipients = ed.getRecipientInfos(); - Collection c = recipients.getRecipients(); + Collection c = recipients.getRecipients(); assertEquals(1, c.size()); - Iterator it = c.iterator(); + Iterator it = c.iterator(); while (it.hasNext()) { - RecipientInformation recipient = (RecipientInformation)it.next(); + RecipientInformation recipient = (RecipientInformation)it.next(); assertEquals(recipient.getKeyEncryptionAlgOID(), PKCSObjectIdentifiers.rsaEncryption.getId()); @@ -325,10 +328,10 @@ public void testKeyTransAES128BufferedStream() edGen.addRecipientInfoGenerator(new JceKeyTransRecipientInfoGenerator(_reciCert).setProvider(BC)); - ByteArrayOutputStream bOut = new ByteArrayOutputStream(); + ByteArrayOutputStream bOut = new ByteArrayOutputStream(); OutputStream out = edGen.open( - bOut, new JceCMSContentEncryptorBuilder(CMSAlgorithm.AES128_CBC).setProvider(BC).build()); + bOut, new JceCMSContentEncryptorBuilder(CMSAlgorithm.AES128_CBC).setProvider(BC).build()); for (int i = 0; i != 2000; i++) { @@ -383,10 +386,10 @@ public void testKeyTransAES128Buffered() edGen.addRecipientInfoGenerator(new JceKeyTransRecipientInfoGenerator(_reciCert).setProvider(BC)); - ByteArrayOutputStream bOut = new ByteArrayOutputStream(); + ByteArrayOutputStream bOut = new ByteArrayOutputStream(); OutputStream out = edGen.open( - bOut, new JceCMSContentEncryptorBuilder(CMSAlgorithm.AES128_CBC).setProvider(BC).build()); + bOut, new JceCMSContentEncryptorBuilder(CMSAlgorithm.AES128_CBC).setProvider(BC).build()); for (int i = 0; i != 2000; i++) { @@ -438,10 +441,10 @@ public void testKeyTransAES128Der() edGen.addRecipientInfoGenerator(new JceKeyTransRecipientInfoGenerator(_reciCert).setProvider(BC)); - ByteArrayOutputStream bOut = new ByteArrayOutputStream(); + ByteArrayOutputStream bOut = new ByteArrayOutputStream(); OutputStream out = edGen.open( - bOut, new JceCMSContentEncryptorBuilder(CMSAlgorithm.AES128_CBC).setProvider(BC).build()); + bOut, new JceCMSContentEncryptorBuilder(CMSAlgorithm.AES128_CBC).setProvider(BC).build()); for (int i = 0; i != 2000; i++) { @@ -490,24 +493,24 @@ public void testKeyTransAES128Throughput() out.close(); - CMSEnvelopedDataParser ep = new CMSEnvelopedDataParser(bOut.toByteArray()); - RecipientInformationStore recipients = ep.getRecipientInfos(); - Collection c = recipients.getRecipients(); - Iterator it = c.iterator(); + CMSEnvelopedDataParser ep = new CMSEnvelopedDataParser(bOut.toByteArray()); + RecipientInformationStore recipients = ep.getRecipientInfos(); + Collection c = recipients.getRecipients(); + Iterator it = c.iterator(); if (it.hasNext()) { - RecipientInformation recipient = (RecipientInformation)it.next(); + RecipientInformation recipient = (RecipientInformation)it.next(); assertEquals(recipient.getKeyEncryptionAlgOID(), PKCSObjectIdentifiers.rsaEncryption.getId()); CMSTypedStream recData = recipient.getContentStream(new JceKeyTransEnvelopedRecipient(_reciKP.getPrivate()).setProvider(BC)); - InputStream dataStream = recData.getContentStream(); + InputStream dataStream = recData.getContentStream(); ByteArrayOutputStream dataOut = new ByteArrayOutputStream(); - int len; - byte[] buf = new byte[BUFFER_SIZE]; - int count = 0; + int len; + byte[] buf = new byte[BUFFER_SIZE]; + int count = 0; while (count != 10 && (len = dataStream.read(buf)) > 0) { @@ -531,7 +534,7 @@ public void testKeyTransAES128Throughput() public void testKeyTransAES128AndOriginatorInfo() throws Exception { - byte[] data = "WallaWallaWashington".getBytes(); + byte[] data = "WallaWallaWashington".getBytes(); CMSEnvelopedDataStreamGenerator edGen = new CMSEnvelopedDataStreamGenerator(); @@ -541,29 +544,29 @@ public void testKeyTransAES128AndOriginatorInfo() edGen.addRecipientInfoGenerator(new JceKeyTransRecipientInfoGenerator(_reciCert).setProvider(BC)); - ByteArrayOutputStream bOut = new ByteArrayOutputStream(); + ByteArrayOutputStream bOut = new ByteArrayOutputStream(); OutputStream out = edGen.open( - bOut, new JceCMSContentEncryptorBuilder(CMSAlgorithm.AES128_CBC).setProvider(BC).build()); + bOut, new JceCMSContentEncryptorBuilder(CMSAlgorithm.AES128_CBC).setProvider(BC).build()); out.write(data); out.close(); - CMSEnvelopedDataParser ep = new CMSEnvelopedDataParser(bOut.toByteArray()); + CMSEnvelopedDataParser ep = new CMSEnvelopedDataParser(bOut.toByteArray()); assertTrue(ep.getOriginatorInfo().getCertificates().getMatches(null).contains(origCert)); - RecipientInformationStore recipients = ep.getRecipientInfos(); + RecipientInformationStore recipients = ep.getRecipientInfos(); assertEquals(ep.getEncryptionAlgOID(), CMSEnvelopedDataGenerator.AES128_CBC); - Collection c = recipients.getRecipients(); - Iterator it = c.iterator(); + Collection c = recipients.getRecipients(); + Iterator it = c.iterator(); while (it.hasNext()) { - RecipientInformation recipient = (RecipientInformation)it.next(); + RecipientInformation recipient = (RecipientInformation)it.next(); assertEquals(recipient.getKeyEncryptionAlgOID(), PKCSObjectIdentifiers.rsaEncryption.getId()); @@ -578,33 +581,33 @@ public void testKeyTransAES128AndOriginatorInfo() public void testKeyTransAES128() throws Exception { - byte[] data = "WallaWallaWashington".getBytes(); + byte[] data = "WallaWallaWashington".getBytes(); CMSEnvelopedDataStreamGenerator edGen = new CMSEnvelopedDataStreamGenerator(); edGen.addRecipientInfoGenerator(new JceKeyTransRecipientInfoGenerator(_reciCert).setProvider(BC)); - ByteArrayOutputStream bOut = new ByteArrayOutputStream(); + ByteArrayOutputStream bOut = new ByteArrayOutputStream(); OutputStream out = edGen.open( - bOut, new JceCMSContentEncryptorBuilder(CMSAlgorithm.AES128_CBC).setProvider(BC).build()); + bOut, new JceCMSContentEncryptorBuilder(CMSAlgorithm.AES128_CBC).setProvider(BC).build()); out.write(data); out.close(); - CMSEnvelopedDataParser ep = new CMSEnvelopedDataParser(bOut.toByteArray()); + CMSEnvelopedDataParser ep = new CMSEnvelopedDataParser(bOut.toByteArray()); - RecipientInformationStore recipients = ep.getRecipientInfos(); + RecipientInformationStore recipients = ep.getRecipientInfos(); assertEquals(ep.getEncryptionAlgOID(), CMSEnvelopedDataGenerator.AES128_CBC); - Collection c = recipients.getRecipients(); - Iterator it = c.iterator(); + Collection c = recipients.getRecipients(); + Iterator it = c.iterator(); while (it.hasNext()) { - RecipientInformation recipient = (RecipientInformation)it.next(); + RecipientInformation recipient = (RecipientInformation)it.next(); assertEquals(recipient.getKeyEncryptionAlgOID(), PKCSObjectIdentifiers.rsaEncryption.getId()); @@ -630,33 +633,33 @@ public void testKeyTransCAST5SunJCE() return; } - byte[] data = "WallaWallaWashington".getBytes(); + byte[] data = "WallaWallaWashington".getBytes(); CMSEnvelopedDataStreamGenerator edGen = new CMSEnvelopedDataStreamGenerator(); edGen.addRecipientInfoGenerator(new JceKeyTransRecipientInfoGenerator(_reciCert).setProvider("SunJCE")); - ByteArrayOutputStream bOut = new ByteArrayOutputStream(); + ByteArrayOutputStream bOut = new ByteArrayOutputStream(); OutputStream out = edGen.open( - bOut, new JceCMSContentEncryptorBuilder(CMSAlgorithm.CAST5_CBC).setProvider(BC).build()); + bOut, new JceCMSContentEncryptorBuilder(CMSAlgorithm.CAST5_CBC).setProvider(BC).build()); out.write(data); out.close(); - CMSEnvelopedDataParser ep = new CMSEnvelopedDataParser(bOut.toByteArray()); + CMSEnvelopedDataParser ep = new CMSEnvelopedDataParser(bOut.toByteArray()); - RecipientInformationStore recipients = ep.getRecipientInfos(); + RecipientInformationStore recipients = ep.getRecipientInfos(); assertEquals(ep.getEncryptionAlgOID(), CMSEnvelopedDataGenerator.CAST5_CBC); - Collection c = recipients.getRecipients(); - Iterator it = c.iterator(); + Collection c = recipients.getRecipients(); + Iterator it = c.iterator(); while (it.hasNext()) { - RecipientInformation recipient = (RecipientInformation)it.next(); + RecipientInformation recipient = (RecipientInformation)it.next(); assertEquals(recipient.getKeyEncryptionAlgOID(), PKCSObjectIdentifiers.rsaEncryption.getId()); @@ -671,36 +674,36 @@ public void testKeyTransCAST5SunJCE() public void testAESKEK() throws Exception { - byte[] data = "WallaWallaWashington".getBytes(); - SecretKey kek = CMSTestUtil.makeAES192Key(); + byte[] data = "WallaWallaWashington".getBytes(); + SecretKey kek = CMSTestUtil.makeAES192Key(); CMSEnvelopedDataStreamGenerator edGen = new CMSEnvelopedDataStreamGenerator(); - byte[] kekId = new byte[] { 1, 2, 3, 4, 5 }; + byte[] kekId = new byte[]{1, 2, 3, 4, 5}; edGen.addRecipientInfoGenerator(new JceKEKRecipientInfoGenerator(kekId, kek).setProvider(BC)); - ByteArrayOutputStream bOut = new ByteArrayOutputStream(); + ByteArrayOutputStream bOut = new ByteArrayOutputStream(); OutputStream out = edGen.open( - bOut, - new JceCMSContentEncryptorBuilder(CMSAlgorithm.DES_EDE3_CBC).setProvider(BC).build()); + bOut, + new JceCMSContentEncryptorBuilder(CMSAlgorithm.DES_EDE3_CBC).setProvider(BC).build()); out.write(data); out.close(); - CMSEnvelopedDataParser ep = new CMSEnvelopedDataParser(bOut.toByteArray()); + CMSEnvelopedDataParser ep = new CMSEnvelopedDataParser(bOut.toByteArray()); - RecipientInformationStore recipients = ep.getRecipientInfos(); + RecipientInformationStore recipients = ep.getRecipientInfos(); assertEquals(ep.getEncryptionAlgOID(), CMSEnvelopedDataGenerator.DES_EDE3_CBC); - Collection c = recipients.getRecipients(); - Iterator it = c.iterator(); + Collection c = recipients.getRecipients(); + Iterator it = c.iterator(); while (it.hasNext()) { - RecipientInformation recipient = (RecipientInformation)it.next(); + RecipientInformation recipient = (RecipientInformation)it.next(); assertEquals(recipient.getKeyEncryptionAlgOID(), "2.16.840.1.101.3.4.1.25"); @@ -715,36 +718,36 @@ public void testAESKEK() public void testTwoAESKEK() throws Exception { - byte[] data = "WallaWallaWashington".getBytes(); - SecretKey kek1 = CMSTestUtil.makeAES192Key(); - SecretKey kek2 = CMSTestUtil.makeAES192Key(); + byte[] data = "WallaWallaWashington".getBytes(); + SecretKey kek1 = CMSTestUtil.makeAES192Key(); + SecretKey kek2 = CMSTestUtil.makeAES192Key(); CMSEnvelopedDataStreamGenerator edGen = new CMSEnvelopedDataStreamGenerator(); - byte[] kekId1 = new byte[] { 1, 2, 3, 4, 5 }; - byte[] kekId2 = new byte[] { 5, 4, 3, 2, 1 }; + byte[] kekId1 = new byte[]{1, 2, 3, 4, 5}; + byte[] kekId2 = new byte[]{5, 4, 3, 2, 1}; edGen.addRecipientInfoGenerator(new JceKEKRecipientInfoGenerator(kekId1, kek1).setProvider(BC)); edGen.addRecipientInfoGenerator(new JceKEKRecipientInfoGenerator(kekId2, kek2).setProvider(BC)); - ByteArrayOutputStream bOut = new ByteArrayOutputStream(); + ByteArrayOutputStream bOut = new ByteArrayOutputStream(); OutputStream out = edGen.open( - bOut, - new JceCMSContentEncryptorBuilder(CMSAlgorithm.DES_EDE3_CBC).setProvider(BC).build()); + bOut, + new JceCMSContentEncryptorBuilder(CMSAlgorithm.DES_EDE3_CBC).setProvider(BC).build()); out.write(data); out.close(); - CMSEnvelopedDataParser ep = new CMSEnvelopedDataParser(bOut.toByteArray()); + CMSEnvelopedDataParser ep = new CMSEnvelopedDataParser(bOut.toByteArray()); - RecipientInformationStore recipients = ep.getRecipientInfos(); + RecipientInformationStore recipients = ep.getRecipientInfos(); assertEquals(ep.getEncryptionAlgOID(), CMSEnvelopedDataGenerator.DES_EDE3_CBC); - RecipientId recSel = new KEKRecipientId(kekId2); + RecipientId recSel = new KEKRecipientId(kekId2); - RecipientInformation recipient = recipients.get(recSel); + RecipientInformation recipient = recipients.get(recSel); assertEquals(recipient.getKeyEncryptionAlgOID(), "2.16.840.1.101.3.4.1.25"); @@ -767,25 +770,25 @@ public void testECKeyAgree() recipientGenerator.addRecipient(_reciEcCert); edGen.addRecipientInfoGenerator(recipientGenerator); - - ByteArrayOutputStream bOut = new ByteArrayOutputStream(); + + ByteArrayOutputStream bOut = new ByteArrayOutputStream(); OutputStream out = edGen.open( - bOut, - new JceCMSContentEncryptorBuilder(CMSAlgorithm.AES128_CBC).setProvider(BC).build()); + bOut, + new JceCMSContentEncryptorBuilder(CMSAlgorithm.AES128_CBC).setProvider(BC).build()); out.write(data); out.close(); - CMSEnvelopedDataParser ep = new CMSEnvelopedDataParser(bOut.toByteArray()); + CMSEnvelopedDataParser ep = new CMSEnvelopedDataParser(bOut.toByteArray()); - RecipientInformationStore recipients = ep.getRecipientInfos(); + RecipientInformationStore recipients = ep.getRecipientInfos(); assertEquals(ep.getEncryptionAlgOID(), CMSEnvelopedDataGenerator.AES128_CBC); - RecipientId recSel = new JceKeyAgreeRecipientId(_reciEcCert); + RecipientId recSel = new JceKeyAgreeRecipientId(_reciEcCert); - RecipientInformation recipient = recipients.get(recSel); + RecipientInformation recipient = recipients.get(recSel); CMSTypedStream recData = recipient.getContentStream(new JceKeyAgreeEnvelopedRecipient(_reciEcKP.getPrivate()).setProvider(BC)); @@ -801,7 +804,7 @@ public void testOriginatorInfo() OriginatorInformation origInfo = env.getOriginatorInfo(); - RecipientInformationStore recipients = env.getRecipientInfos(); + RecipientInformationStore recipients = env.getRecipientInfos(); assertEquals(new X500Name("C=US,O=U.S. Government,OU=HSPD12Lab,OU=Agents,CN=user1"), ((X509CertificateHolder)origInfo.getCertificates().getMatches(null).iterator().next()).getSubject()); assertEquals(CMSEnvelopedDataGenerator.DES_EDE3_CBC, env.getEncryptionAlgOID());