Skip to content

Commit

Permalink
updated KEMRecipientInfo to RFC 9629
Browse files Browse the repository at this point in the history
  • Loading branch information
dghgit committed Aug 25, 2024
1 parent 9c96f9a commit 108fcf5
Show file tree
Hide file tree
Showing 2 changed files with 138 additions and 2 deletions.
18 changes: 16 additions & 2 deletions util/src/main/java/org/bouncycastle/asn1/cms/KEMRecipientInfo.java
Original file line number Diff line number Diff line change
Expand Up @@ -12,16 +12,21 @@
import org.bouncycastle.asn1.x509.AlgorithmIdentifier;

/**
* <p>
* Defined in <a href="https://datatracker.ietf.org/doc/rfc9629/">RFC 9629</a>.
* </p>
* <pre>
* KEMRecipientInfo ::= SEQUENCE {
* version CMSVersion, -- always set to 0
* rid RecipientIdentifier,
* kem KEMAlgorithmIdentifier,
* kemct OCTET STRING,
* kdf KeyDerivationAlgorithmIdentifier,
* kekLength INTEGER (1..MAX),
* kekLength INTEGER (1..65535),
* ukm [0] EXPLICIT UserKeyingMaterial OPTIONAL,
* wrap KeyEncryptionAlgorithmIdentifier,
* encryptedKey EncryptedKey }
* </pre>
*/
public class KEMRecipientInfo
extends ASN1Object
Expand All @@ -47,6 +52,10 @@ public KEMRecipientInfo(RecipientIdentifier rid, AlgorithmIdentifier kem, ASN1Oc
{
throw new NullPointerException("wrap cannot be null");
}
if (kekLength.intValueExact() > 65535)
{
throw new IllegalArgumentException("kekLength must be <= 65535");
}
this.cmsVersion = new ASN1Integer(0);
this.rid = rid;
this.kem = kem;
Expand Down Expand Up @@ -76,7 +85,7 @@ private KEMRecipientInfo(ASN1Sequence seq)
{
if (seq.size() < 8 || seq.size() > 9)
{
throw new IllegalArgumentException("Bad sequence size: " + seq.size());
throw new IllegalArgumentException("bad sequence size: " + seq.size());
}

cmsVersion = ASN1Integer.getInstance(seq.getObjectAt(0));
Expand All @@ -86,6 +95,11 @@ private KEMRecipientInfo(ASN1Sequence seq)
kdf = AlgorithmIdentifier.getInstance(seq.getObjectAt(4));
kekLength = ASN1Integer.getInstance(seq.getObjectAt(5));

if (kekLength.intValueExact() > 65535)
{
throw new IllegalArgumentException("kekLength must be <= 65535");
}

int elt = 6;
if (seq.getObjectAt(6) instanceof ASN1TaggedObject)
{
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
package org.bouncycastle.asn1.cms.test;

import junit.framework.TestCase;
import org.bouncycastle.asn1.ASN1Encodable;
import org.bouncycastle.asn1.ASN1Integer;
import org.bouncycastle.asn1.ASN1Primitive;
import org.bouncycastle.asn1.DEROctetString;
import org.bouncycastle.asn1.DERSequence;
import org.bouncycastle.asn1.cms.KEMRecipientInfo;
import org.bouncycastle.asn1.cms.RecipientIdentifier;
import org.bouncycastle.asn1.nist.NISTObjectIdentifiers;
import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
import org.bouncycastle.asn1.x9.X9ObjectIdentifiers;
import org.bouncycastle.util.encoders.Base64;

public class KEMRecipientInfoTest
extends TestCase
{
private static byte[] outOfRangeEnc = Base64.decode("MDoCAQCAADALBglghkgBZQMEBAEEADAMBgorgQUQhkgJLAECAgMKrmCgAgQAMAsGCWCGSAFlAwQBMAQA");

public void testOutOfRange()
throws Exception
{
try
{
new KEMRecipientInfo(
new RecipientIdentifier(new DEROctetString(new byte[0])),
new AlgorithmIdentifier(NISTObjectIdentifiers.id_alg_ml_kem_512),
new DEROctetString(new byte[0]),
new AlgorithmIdentifier(X9ObjectIdentifiers.id_kdf_kdf3),
new ASN1Integer(700000), new DEROctetString(new byte[0]),
new AlgorithmIdentifier(NISTObjectIdentifiers.id_aes256_wrap_pad),
new DEROctetString(new byte[0]));
fail("no exception");
}
catch (IllegalArgumentException e)
{
assertEquals("kekLength must be <= 65535", e.getMessage());
}

try
{
KEMRecipientInfo.getInstance(ASN1Primitive.fromByteArray(outOfRangeEnc));
fail("no exception");
}
catch (IllegalArgumentException e)
{
assertEquals("kekLength must be <= 65535", e.getMessage());
}
}

public void testNullWrap()
throws Exception
{
try
{
new KEMRecipientInfo(
new RecipientIdentifier(new DEROctetString(new byte[0])),
new AlgorithmIdentifier(NISTObjectIdentifiers.id_alg_ml_kem_512),
new DEROctetString(new byte[0]),
new AlgorithmIdentifier(X9ObjectIdentifiers.id_kdf_kdf3),
new ASN1Integer(7000), new DEROctetString(new byte[0]),
null,
new DEROctetString(new byte[0]));
fail("no exception");
}
catch (NullPointerException e)
{
assertEquals("wrap cannot be null", e.getMessage());
}
}

public void testNullKem()
throws Exception
{
try
{
new KEMRecipientInfo(
new RecipientIdentifier(new DEROctetString(new byte[0])),
null,
new DEROctetString(new byte[0]),
new AlgorithmIdentifier(X9ObjectIdentifiers.id_kdf_kdf3),
new ASN1Integer(7000), new DEROctetString(new byte[0]),
new AlgorithmIdentifier(NISTObjectIdentifiers.id_aes256_wrap_pad),
new DEROctetString(new byte[0]));
fail("no exception");
}
catch (NullPointerException e)
{
assertEquals("kem cannot be null", e.getMessage());
}
}

public void testSequenceSize()
throws Exception
{
try
{
KEMRecipientInfo.getInstance(new DERSequence(new RecipientIdentifier(new DEROctetString(new byte[0]))));
fail("no exception");
}
catch (IllegalArgumentException e)
{
assertEquals("bad sequence size: 1", e.getMessage());
}

try
{
ASN1Encodable[] elements = new ASN1Encodable[10];
for (int i = 0; i != elements.length; i++)
{
elements[i] = new ASN1Integer(1);
}
KEMRecipientInfo.getInstance(new DERSequence(elements));
fail("no exception");
}
catch (IllegalArgumentException e)
{
assertEquals("bad sequence size: 10", e.getMessage());
}
}
}

0 comments on commit 108fcf5

Please sign in to comment.