Skip to content

Commit

Permalink
Rewrite generateCounterSigners
Browse files Browse the repository at this point in the history
- restore null check in ContentInfo constructor
  • Loading branch information
peterdettman committed Dec 18, 2024
1 parent 6b80483 commit c609ec2
Show file tree
Hide file tree
Showing 2 changed files with 98 additions and 74 deletions.
161 changes: 93 additions & 68 deletions pkix/src/main/java/org/bouncycastle/cms/CMSSignedDataGenerator.java
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,6 @@
public class CMSSignedDataGenerator
extends CMSSignedGenerator
{
private List signerInfs = new ArrayList();
private boolean isDefiniteLength = false;

/**
Expand Down Expand Up @@ -105,12 +104,7 @@ public CMSSignedData generate(
boolean encapsulate)
throws CMSException
{
if (!signerInfs.isEmpty())
{
throw new IllegalStateException("this method can only be used with SignerInfoGenerator");
}

// TODO
// TODO
// if (signerInfs.isEmpty())
// {
// /* RFC 3852 5.2
Expand Down Expand Up @@ -141,7 +135,7 @@ public CMSSignedData generate(
// }

Set<AlgorithmIdentifier> digestAlgs = new LinkedHashSet<AlgorithmIdentifier>();
ASN1EncodableVector signerInfos = new ASN1EncodableVector();
ASN1EncodableVector signerInfos = new ASN1EncodableVector();

digests.clear(); // clear the current preserved digest state

Expand All @@ -159,92 +153,59 @@ public CMSSignedData generate(
//
// add the SignerInfo objects
//
ASN1ObjectIdentifier contentTypeOID = content.getContentType();

ASN1OctetString octs = null;
ASN1ObjectIdentifier encapContentType = content.getContentType();
ASN1OctetString encapContent = null;

// TODO[cms] Could be unnecessary copy e.g. if content is CMSProcessableByteArray (add hasContent method?)
if (content.getContent() != null)
{
ByteArrayOutputStream bOut = null;

if (encapsulate)
{
bOut = new ByteArrayOutputStream();
}

OutputStream cOut = CMSUtils.attachSignersToOutputStream(signerGens, bOut);

// Just in case it's unencapsulated and there are no signers!
cOut = CMSUtils.getSafeOutputStream(cOut);

try
{
content.write(cOut);
ByteArrayOutputStream bOut = new ByteArrayOutputStream();

cOut.close();
}
catch (IOException e)
{
throw new CMSException("data processing exception: " + e.getMessage(), e);
}
writeContentViaSignerGens(content, bOut);

if (encapsulate)
{
if (isDefiniteLength)
{
octs = new DEROctetString(bOut.toByteArray());
encapContent = new DEROctetString(bOut.toByteArray());
}
else
{
octs = new BEROctetString(bOut.toByteArray());
encapContent = new BEROctetString(bOut.toByteArray());
}
}
else
{
writeContentViaSignerGens(content, null);
}
}

for (Iterator it = signerGens.iterator(); it.hasNext();)
{
SignerInfoGenerator sGen = (SignerInfoGenerator)it.next();
SignerInfo inf = sGen.generate(contentTypeOID);

digestAlgs.add(inf.getDigestAlgorithm());
signerInfos.add(inf);

byte[] calcDigest = sGen.getCalculatedDigest();

if (calcDigest != null)
{
digests.put(inf.getDigestAlgorithm().getAlgorithm().getId(), calcDigest);
}
SignerInfoGenerator signerGen = (SignerInfoGenerator)it.next();
SignerInfo signerInfo = generateSignerInfo(signerGen, encapContentType);
digestAlgs.add(signerInfo.getDigestAlgorithm());
signerInfos.add(signerInfo);
}

ASN1Set certificates = createSetFromList(certs, isDefiniteLength);
ASN1Set certificates = createSetFromList(this.certs, isDefiniteLength);

ASN1Set certrevlist = createSetFromList(crls, isDefiniteLength);
ASN1Set crls = createSetFromList(this.crls, isDefiniteLength);

ContentInfo encInfo = new ContentInfo(contentTypeOID, octs);
ContentInfo encapContentInfo = new ContentInfo(encapContentType, encapContent);

SignedData sd = new SignedData(
CMSUtils.convertToDlSet(digestAlgs),
encInfo,
certificates,
certrevlist,
new DERSet(signerInfos));
SignedData signedData = new SignedData(
CMSUtils.convertToDlSet(digestAlgs),
encapContentInfo,
certificates,
crls,
new DERSet(signerInfos));

ContentInfo contentInfo = new ContentInfo(
CMSObjectIdentifiers.signedData, sd);
ContentInfo contentInfo = new ContentInfo(CMSObjectIdentifiers.signedData, signedData);

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.
Expand All @@ -255,7 +216,71 @@ private static ASN1Set createSetFromList(List list, boolean isDefiniteLength)
public SignerInformationStore generateCounterSigners(SignerInformation signer)
throws CMSException
{
return this.generate(new CMSProcessableByteArray(null, signer.getSignature()), false).getSignerInfos();
digests.clear();

CMSTypedData content = new CMSProcessableByteArray(null, signer.getSignature());

ArrayList signerInformations = new ArrayList();

for (Iterator it = _signers.iterator(); it.hasNext();)
{
SignerInformation _signer = (SignerInformation)it.next();
SignerInfo signerInfo = _signer.toASN1Structure();
signerInformations.add(new SignerInformation(signerInfo, null, content, null));
}

writeContentViaSignerGens(content, null);

for (Iterator it = signerGens.iterator(); it.hasNext();)
{
SignerInfoGenerator signerGen = (SignerInfoGenerator)it.next();
SignerInfo signerInfo = generateSignerInfo(signerGen, null);
signerInformations.add(new SignerInformation(signerInfo, null, content, null));
}

return new SignerInformationStore(signerInformations);
}

private SignerInfo generateSignerInfo(SignerInfoGenerator signerGen, ASN1ObjectIdentifier contentType)
throws CMSException
{
SignerInfo signerInfo = signerGen.generate(contentType);

byte[] calcDigest = signerGen.getCalculatedDigest();
if (calcDigest != null)
{
digests.put(signerInfo.getDigestAlgorithm().getAlgorithm().getId(), calcDigest);
}

return signerInfo;
}

private void writeContentViaSignerGens(CMSTypedData content, OutputStream s)
throws CMSException
{
OutputStream cOut = CMSUtils.attachSignersToOutputStream(signerGens, s);

// Just in case it's unencapsulated and there are no signers!
cOut = CMSUtils.getSafeOutputStream(cOut);

try
{
content.write(cOut);

cOut.close();
}
catch (IOException e)
{
throw new CMSException("data processing exception: " + e.getMessage(), e);
}
}

private static ASN1Set createSetFromList(List list, boolean isDefiniteLength)
{
return list.size() < 1
? null
: isDefiniteLength
? CMSUtils.createDlSetFromList(list)
: CMSUtils.createBerSetFromList(list);
}
}

11 changes: 5 additions & 6 deletions util/src/main/java/org/bouncycastle/asn1/cms/ContentInfo.java
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ public static ContentInfo getInstance(
ASN1TaggedObject obj,
boolean explicit)
{
return getInstance(ASN1Sequence.getInstance(obj, explicit));
return new ContentInfo(ASN1Sequence.getInstance(obj, explicit));
}

private ContentInfo(
Expand Down Expand Up @@ -104,11 +104,10 @@ public ContentInfo(
ASN1ObjectIdentifier contentType,
ASN1Encodable content)
{
// TODO[cms] Blocked by CMSSignedDataGenerator.generateCounterSigners transient usage of null here
// if (contentType == null)
// {
// throw new NullPointerException("'contentType' cannot be null");
// }
if (contentType == null)
{
throw new NullPointerException("'contentType' cannot be null");
}

this.contentType = contentType;
this.content = content;
Expand Down

0 comments on commit c609ec2

Please sign in to comment.