Skip to content

Commit

Permalink
Refactor around Extension (reduce array copies)
Browse files Browse the repository at this point in the history
  • Loading branch information
peterdettman committed Nov 6, 2024
1 parent 092e85d commit f8cd3f3
Show file tree
Hide file tree
Showing 7 changed files with 91 additions and 68 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -266,7 +266,7 @@ public static Extension create(
ASN1Encodable value)
throws IOException
{
return new Extension(extnId, critical, value.toASN1Primitive().getEncoded());
return new Extension(extnId, critical, new DEROctetString(value.toASN1Primitive().getEncoded()));
}

private Extension(ASN1Sequence seq)
Expand Down
127 changes: 71 additions & 56 deletions core/src/main/java/org/bouncycastle/asn1/x509/ExtensionsGenerator.java
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@
import org.bouncycastle.asn1.ASN1Sequence;
import org.bouncycastle.asn1.DEROctetString;
import org.bouncycastle.asn1.DERSequence;
import org.bouncycastle.util.Arrays;

/**
* Generator for X.509 extensions
Expand Down Expand Up @@ -55,13 +54,17 @@ public void reset()
* @param critical true if critical, false otherwise.
* @param value the ASN.1 object to be included in the extension.
*/
public void addExtension(
ASN1ObjectIdentifier oid,
boolean critical,
ASN1Encodable value)
throws IOException
public void addExtension(ASN1ObjectIdentifier oid, boolean critical, ASN1Encodable value) throws IOException
{
this.addExtension(oid, critical, value.toASN1Primitive().getEncoded(ASN1Encoding.DER));
Extension existingExtension = (Extension)extensions.get(oid);
if (existingExtension != null)
{
implAddExtensionDup(existingExtension, critical, value.toASN1Primitive().getEncoded(ASN1Encoding.DER));
}
else
{
implAddExtension(new Extension(oid, critical, new DEROctetString(value)));
}
}

/**
Expand All @@ -72,47 +75,16 @@ public void addExtension(
* @param critical true if critical, false otherwise.
* @param value the byte array to be wrapped.
*/
public void addExtension(
ASN1ObjectIdentifier oid,
boolean critical,
byte[] value)
public void addExtension(ASN1ObjectIdentifier oid, boolean critical, byte[] value)
{
if (extensions.containsKey(oid))
Extension existingExtension = (Extension)extensions.get(oid);
if (existingExtension != null)
{
if (dupsAllowed.contains(oid))
{
Extension existingExtension = (Extension)extensions.get(oid);
ASN1Sequence seq1 = ASN1Sequence.getInstance(DEROctetString.getInstance(existingExtension.getExtnValue()).getOctets());
ASN1Sequence seq2 = ASN1Sequence.getInstance(value);

ASN1EncodableVector items = new ASN1EncodableVector(seq1.size() + seq2.size());
for (Enumeration en = seq1.getObjects(); en.hasMoreElements();)
{
items.add((ASN1Encodable)en.nextElement());
}
for (Enumeration en = seq2.getObjects(); en.hasMoreElements();)
{
items.add((ASN1Encodable)en.nextElement());
}

try
{
extensions.put(oid, new Extension(oid, critical, new DERSequence(items).getEncoded()));
}
catch (IOException e)
{
throw new ASN1ParsingException(e.getMessage(), e);
}
}
else
{
throw new IllegalArgumentException("extension " + oid + " already added");
}
implAddExtensionDup(existingExtension, critical, value);
}
else
{
extOrdering.addElement(oid);
extensions.put(oid, new Extension(oid, critical, new DEROctetString(Arrays.clone(value))));
implAddExtension(new Extension(oid, critical, value));
}
}

Expand All @@ -124,15 +96,31 @@ public void addExtension(
public void addExtension(
Extension extension)
{
if (extensions.containsKey(extension.getExtnId()))
if (hasExtension(extension.getExtnId()))
{
throw new IllegalArgumentException("extension " + extension.getExtnId() + " already added");
}

extOrdering.addElement(extension.getExtnId());
extensions.put(extension.getExtnId(), extension);
implAddExtension(extension);
}

/** @deprecated Use addExtensions instead. */
public void addExtension(Extensions extensions)
{
addExtensions(extensions);
}

public void addExtensions(Extensions extensions)
{
ASN1ObjectIdentifier[] oids = extensions.getExtensionOIDs();
for (int i = 0; i != oids.length; i++)
{
ASN1ObjectIdentifier ident = oids[i];
Extension ext = extensions.getExtension(ident);
addExtension(ASN1ObjectIdentifier.getInstance(ident), ext.isCritical(), ext.getExtnValue().getOctets());
}
}

/**
* Replace an extension with the given oid and the passed in value to be included
* in the OCTET STRING associated with the extension.
Expand All @@ -147,7 +135,7 @@ public void replaceExtension(
ASN1Encodable value)
throws IOException
{
this.replaceExtension(oid, critical, value.toASN1Primitive().getEncoded(ASN1Encoding.DER));
replaceExtension(new Extension(oid, critical, new DEROctetString(value)));
}

/**
Expand All @@ -163,7 +151,7 @@ public void replaceExtension(
boolean critical,
byte[] value)
{
this.replaceExtension(new Extension(oid, critical, value));
replaceExtension(new Extension(oid, critical, value));
}

/**
Expand All @@ -174,7 +162,7 @@ public void replaceExtension(
public void replaceExtension(
Extension extension)
{
if (!extensions.containsKey(extension.getExtnId()))
if (!hasExtension(extension.getExtnId()))
{
throw new IllegalArgumentException("extension " + extension.getExtnId() + " not present");
}
Expand All @@ -190,7 +178,7 @@ public void replaceExtension(
public void removeExtension(
ASN1ObjectIdentifier oid)
{
if (!extensions.containsKey(oid))
if (!hasExtension(oid))
{
throw new IllegalArgumentException("extension " + oid + " not present");
}
Expand Down Expand Up @@ -248,14 +236,41 @@ public Extensions generate()
return new Extensions(exts);
}

public void addExtension(Extensions extensions)
private void implAddExtension(Extension extension)
{
ASN1ObjectIdentifier[] oids = extensions.getExtensionOIDs();
for (int i = 0; i != oids.length; i++)
extOrdering.addElement(extension.getExtnId());
extensions.put(extension.getExtnId(), extension);
}

private void implAddExtensionDup(Extension existingExtension, boolean critical, byte[] value)
{
ASN1ObjectIdentifier oid = existingExtension.getExtnId();
if (!dupsAllowed.contains(oid))
{
ASN1ObjectIdentifier ident = oids[i];
Extension ext = extensions.getExtension(ident);
addExtension(ASN1ObjectIdentifier.getInstance(ident), ext.isCritical(), ext.getExtnValue().getOctets());
throw new IllegalArgumentException("extension " + oid + " already added");
}

ASN1Sequence seq1 = ASN1Sequence.getInstance(
DEROctetString.getInstance(existingExtension.getExtnValue()).getOctets());
ASN1Sequence seq2 = ASN1Sequence.getInstance(value);

ASN1EncodableVector items = new ASN1EncodableVector(seq1.size() + seq2.size());
for (Enumeration en = seq1.getObjects(); en.hasMoreElements();)
{
items.add((ASN1Encodable)en.nextElement());
}
for (Enumeration en = seq2.getObjects(); en.hasMoreElements();)
{
items.add((ASN1Encodable)en.nextElement());
}

try
{
extensions.put(oid, new Extension(oid, critical, new DEROctetString(new DERSequence(items))));
}
catch (IOException e)
{
throw new ASN1ParsingException(e.getMessage(), e);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -412,7 +412,7 @@ public void testDuplicateExtensions()
//

ExtensionsGenerator genX = new ExtensionsGenerator();
genX.addExtension(ext);
genX.addExtensions(ext);

ext = Extensions.getInstance(ASN1Sequence.getInstance(genX.generate().getEncoded()));
returnedExtension = ext.getExtension(Extension.subjectAlternativeName);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,10 @@
import java.util.Locale;

import org.bouncycastle.asn1.ASN1Encodable;
import org.bouncycastle.asn1.ASN1Encoding;
import org.bouncycastle.asn1.ASN1GeneralizedTime;
import org.bouncycastle.asn1.ASN1Integer;
import org.bouncycastle.asn1.ASN1ObjectIdentifier;
import org.bouncycastle.asn1.DEROctetString;
import org.bouncycastle.asn1.DERSet;
import org.bouncycastle.asn1.x509.AttCertIssuer;
import org.bouncycastle.asn1.x509.Attribute;
Expand Down Expand Up @@ -249,7 +249,8 @@ public X509v2AttributeCertificateBuilder replaceExtension(
{
try
{
extGenerator = CertUtils.doReplaceExtension(extGenerator, new Extension(oid, isCritical, value.toASN1Primitive().getEncoded(ASN1Encoding.DER)));
extGenerator = CertUtils.doReplaceExtension(extGenerator,
new Extension(oid, isCritical, new DEROctetString(value)));
}
catch (IOException e)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
import org.bouncycastle.asn1.ASN1ObjectIdentifier;
import org.bouncycastle.asn1.ASN1Sequence;
import org.bouncycastle.asn1.DERBitString;
import org.bouncycastle.asn1.DEROctetString;
import org.bouncycastle.asn1.DERSequence;
import org.bouncycastle.asn1.x500.X500Name;
import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
Expand Down Expand Up @@ -384,7 +385,8 @@ public X509v2CRLBuilder replaceExtension(
{
try
{
extGenerator = CertUtils.doReplaceExtension(extGenerator, new Extension(oid, isCritical, value.toASN1Primitive().getEncoded(ASN1Encoding.DER)));
extGenerator = CertUtils.doReplaceExtension(extGenerator,
new Extension(oid, isCritical, new DEROctetString(value)));
}
catch (IOException e)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
import org.bouncycastle.asn1.ASN1ObjectIdentifier;
import org.bouncycastle.asn1.DERBitString;
import org.bouncycastle.asn1.DERNull;
import org.bouncycastle.asn1.DEROctetString;
import org.bouncycastle.asn1.DERSequence;
import org.bouncycastle.asn1.x500.X500Name;
import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
Expand Down Expand Up @@ -274,7 +275,8 @@ public X509v3CertificateBuilder replaceExtension(
{
try
{
extGenerator = CertUtils.doReplaceExtension(extGenerator, new Extension(oid, isCritical, value.toASN1Primitive().getEncoded(ASN1Encoding.DER)));
extGenerator = CertUtils.doReplaceExtension(extGenerator,
new Extension(oid, isCritical, new DEROctetString(value)));
}
catch (IOException e)
{
Expand Down Expand Up @@ -452,7 +454,7 @@ public X509CertificateHolder build(
// the altSignatureValue is not present yet, but it must be in the deltaCertificate and
// it must be different (by definition!). We add a dummy one to trigger inclusion.
ExtensionsGenerator tmpExtGen = new ExtensionsGenerator();
tmpExtGen.addExtension(extGenerator.generate());
tmpExtGen.addExtensions(extGenerator.generate());
tmpExtGen.addExtension(Extension.altSignatureValue, false, DERNull.INSTANCE);

DeltaCertificateDescriptor descriptor = DeltaCertificateTool.trimDeltaCertificateDescriptor(
Expand Down
13 changes: 8 additions & 5 deletions prov/src/main/java/org/bouncycastle/jce/provider/OcspCache.java
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
import org.bouncycastle.asn1.ASN1ObjectIdentifier;
import org.bouncycastle.asn1.ASN1OctetString;
import org.bouncycastle.asn1.ASN1Sequence;
import org.bouncycastle.asn1.DEROctetString;
import org.bouncycastle.asn1.DERSequence;
import org.bouncycastle.asn1.ocsp.BasicOCSPResponse;
import org.bouncycastle.asn1.ocsp.CertID;
Expand All @@ -39,6 +40,7 @@
import org.bouncycastle.asn1.x509.Extensions;
import org.bouncycastle.jcajce.PKIXCertRevocationCheckerParameters;
import org.bouncycastle.jcajce.util.JcaJceHelper;
import org.bouncycastle.util.Arrays;
import org.bouncycastle.util.io.Streams;

class OcspCache
Expand Down Expand Up @@ -108,15 +110,16 @@ static OCSPResponse getOcspResponse(
for (int i = 0; i != exts.size(); i++)
{
Extension ext = (Extension)exts.get(i);
byte[] value = ext.getValue();

if (OCSPObjectIdentifiers.id_pkix_ocsp_nonce.getId().equals(ext.getId()))
ASN1ObjectIdentifier oid = new ASN1ObjectIdentifier(ext.getId());
ASN1OctetString value = new DEROctetString(ext.getValue());

if (OCSPObjectIdentifiers.id_pkix_ocsp_nonce.equals(oid))
{
nonce = value;
nonce = Arrays.clone(value.getOctets());
}

requestExtensions.add(new org.bouncycastle.asn1.x509.Extension(
new ASN1ObjectIdentifier(ext.getId()), ext.isCritical(), value));
requestExtensions.add(new org.bouncycastle.asn1.x509.Extension(oid, ext.isCritical(), value));
}

// TODO: configure originator
Expand Down

0 comments on commit f8cd3f3

Please sign in to comment.