Skip to content

Commit

Permalink
Adapt to draft-ietf-lamps-rfc4210bis - 08
Browse files Browse the repository at this point in the history
  • Loading branch information
Akretsch committed Mar 6, 2024
1 parent ced10a4 commit f5706d9
Show file tree
Hide file tree
Showing 16 changed files with 144 additions and 199 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ public interface RevocationContext {

/**
* get revocation reason to use
* @return revocation reason to use
*/
default int getRevocationReason() {
return CRLReason.UNSPECIFIED.ordinal();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,7 @@ public interface EnrollmentResult {
* towards the CA
*
* @param clientContext client specific configuration
* @throws GeneralSecurityException
* @throws GeneralSecurityException in case of internal error
*/
public CmpClient(
String certProfile,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,17 +17,23 @@
*/
package com.siemens.pki.cmpracomponent.cmpextension;

import org.bouncycastle.asn1.ASN1Encodable;
import org.bouncycastle.asn1.ASN1EncodableVector;
import org.bouncycastle.asn1.ASN1Integer;
import org.bouncycastle.asn1.ASN1Object;
import org.bouncycastle.asn1.ASN1OctetString;
import org.bouncycastle.asn1.ASN1Primitive;
import org.bouncycastle.asn1.ASN1Sequence;
import org.bouncycastle.asn1.ASN1TaggedObject;
import org.bouncycastle.asn1.DEROctetString;
import org.bouncycastle.asn1.DERSequence;
import org.bouncycastle.asn1.DERTaggedObject;
import org.bouncycastle.asn1.x509.AlgorithmIdentifier;

/**
* KemBMParameter ::= SEQUENCE {
* kdf AlgorithmIdentifier{KEY-DERIVATION, {...}},
* kemContext [0] OCTET STRING OPTIONAL,
* len INTEGER (1..MAX), -- output length of the KDF
* mac AlgorithmIdentifier{MAC-ALGORITHM, {...}}
* }
Expand All @@ -46,30 +52,55 @@ public static KemBMParameter getInstance(Object o) {
}

private final AlgorithmIdentifier kdf;
private final ASN1OctetString kemContext;
private final ASN1Integer len;

private final AlgorithmIdentifier mac;

public KemBMParameter(AlgorithmIdentifier kdf, ASN1Integer len, AlgorithmIdentifier mac) {
public KemBMParameter(
AlgorithmIdentifier kdf, ASN1OctetString kemContext, ASN1Integer len, AlgorithmIdentifier mac) {
this.kdf = kdf;
this.kemContext = kemContext;
this.len = len;
this.mac = mac;
}

public KemBMParameter(AlgorithmIdentifier kdf, int len, AlgorithmIdentifier mac) {
this(kdf, new ASN1Integer(len), mac);
public KemBMParameter(AlgorithmIdentifier kdf, byte[] kemContext, int len, AlgorithmIdentifier mac) {
this(kdf, kemContext != null ? new DEROctetString(kemContext) : null, new ASN1Integer(len), mac);
}

private KemBMParameter(ASN1Sequence seq) {
kdf = AlgorithmIdentifier.getInstance(seq.getObjectAt(0));
len = ASN1Integer.getInstance(seq.getObjectAt(1));
mac = AlgorithmIdentifier.getInstance(seq.getObjectAt(2));
final ASN1Encodable optionalKemContext = seq.getObjectAt(1);
if (optionalKemContext instanceof ASN1TaggedObject) {
final ASN1TaggedObject taggedKemContext = (ASN1TaggedObject) optionalKemContext;
if (taggedKemContext.getTagNo() != 0) {
throw new IllegalArgumentException("kemContext must be tagged with [0]");
}
kemContext = ASN1OctetString.getInstance(taggedKemContext, true);
len = ASN1Integer.getInstance(seq.getObjectAt(2));
mac = AlgorithmIdentifier.getInstance(seq.getObjectAt(3));
} else {
kemContext = null;
len = ASN1Integer.getInstance(seq.getObjectAt(1));
mac = AlgorithmIdentifier.getInstance(seq.getObjectAt(2));
}
}

private void addOptional(ASN1EncodableVector v, int tagNo, ASN1Encodable obj) {
if (obj != null) {
v.add(new DERTaggedObject(true, tagNo, obj));
}
}

public AlgorithmIdentifier getKdf() {
return kdf;
}

public ASN1OctetString getKemContext() {
return kemContext;
}

public ASN1Integer getLen() {
return len;
}
Expand All @@ -91,9 +122,9 @@ public AlgorithmIdentifier getMac() {
*/
@Override
public ASN1Primitive toASN1Primitive() {
final ASN1EncodableVector v = new ASN1EncodableVector(3);

final ASN1EncodableVector v = new ASN1EncodableVector(4);
v.add(kdf);
addOptional(v, 0, kemContext);
v.add(len);
v.add(mac);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,31 +17,29 @@
*/
package com.siemens.pki.cmpracomponent.cmpextension;

import java.util.Enumeration;
import org.bouncycastle.asn1.ASN1Encodable;
import org.bouncycastle.asn1.ASN1EncodableVector;
import org.bouncycastle.asn1.ASN1Integer;
import org.bouncycastle.asn1.ASN1Object;
import org.bouncycastle.asn1.ASN1OctetString;
import org.bouncycastle.asn1.ASN1Primitive;
import org.bouncycastle.asn1.ASN1Sequence;
import org.bouncycastle.asn1.ASN1TaggedObject;
import org.bouncycastle.asn1.BEROctetString;
import org.bouncycastle.asn1.DERSequence;
import org.bouncycastle.asn1.DERTaggedObject;
import org.bouncycastle.asn1.cmp.PKIFreeText;
import org.bouncycastle.asn1.x509.AlgorithmIdentifier;

/*
* KemOtherInfo ::= SEQUENCE {
* staticString PKIFreeText,
* transactionID [0] OCTET STRING OPTIONAL,
* senderNonce [1] OCTET STRING OPTIONAL,
* recipNonce [2] OCTET STRING OPTIONAL,
* len INTEGER (1..MAX),
* mac AlgorithmIdentifier{MAC-ALGORITHM, {...}}
* ct OCTET STRING
* }
*/
KemOtherInfo ::= SEQUENCE {
staticString PKIFreeText,
-- MUST be "CMP-KEM"
transactionID OCTET STRING,
-- MUST contain the values from the message previously received
-- containing the ciphertext (ct) in KemCiphertextInfo
kemContext [0] OCTET STRING OPTIONAL
-- MAY contain additional algorithm specific context information
}
*/

public class KemOtherInfo extends ASN1Object {

Expand All @@ -60,67 +58,37 @@ public static KemOtherInfo getInstance(Object o) {
}

private final PKIFreeText staticString;
private ASN1OctetString transactionID;
private ASN1OctetString senderNonce;
private ASN1OctetString recipNonce;
private final ASN1Integer len;
private final AlgorithmIdentifier mac;
private final ASN1OctetString ct;

public KemOtherInfo(
ASN1OctetString transactionID,
ASN1OctetString senderNonce,
ASN1OctetString recipNonce,
ASN1Integer len,
AlgorithmIdentifier mac,
ASN1OctetString ct) {
private final ASN1OctetString transactionID;
private final ASN1OctetString kemContext;

public KemOtherInfo(ASN1OctetString transactionID, ASN1OctetString kemContext) {
this.staticString = DEFAULT_staticString;
this.transactionID = transactionID;
this.senderNonce = senderNonce;
this.recipNonce = recipNonce;
this.len = len;
this.mac = mac;
this.ct = ct;
}

public KemOtherInfo(
ASN1OctetString transactionID,
ASN1OctetString senderNonce,
ASN1OctetString recipNonce,
long len,
AlgorithmIdentifier mac,
ASN1OctetString ct) {
this(transactionID, senderNonce, recipNonce, new ASN1Integer(len), mac, ct);
this.kemContext = kemContext;
}

private KemOtherInfo(ASN1Sequence seq) {

final Enumeration en = seq.getObjects();

staticString = PKIFreeText.getInstance(en.nextElement());
ASN1Object next = null;
while (en.hasMoreElements()) {
next = (ASN1Object) en.nextElement();
if (!(next instanceof ASN1TaggedObject)) {
break;
}
final ASN1TaggedObject tagged = (ASN1TaggedObject) next;
switch (tagged.getTagNo()) {
case 0:
transactionID = ASN1OctetString.getInstance(tagged, true);
break;
case 1:
senderNonce = ASN1OctetString.getInstance(tagged, true);
break;
case 2:
recipNonce = ASN1OctetString.getInstance(tagged, true);
default:
throw new IllegalArgumentException("unknown tag number: " + tagged.getTagNo());
staticString = PKIFreeText.getInstance(seq.getObjectAt(0));
transactionID = ASN1OctetString.getInstance(seq.getObjectAt(1));
if (seq.size() > 2) {
final ASN1Encodable optionalKemContext = seq.getObjectAt(2);
if (optionalKemContext instanceof ASN1TaggedObject) {
final ASN1TaggedObject taggedKemContext = (ASN1TaggedObject) optionalKemContext;
if (taggedKemContext.getTagNo() == 0) {
kemContext = ASN1OctetString.getInstance(taggedKemContext, true);
return;
}
}
throw new IllegalArgumentException("kemContext must be tagged with [0]");
}
len = ASN1Integer.getInstance(next);
mac = AlgorithmIdentifier.getInstance(en.nextElement());
ct = ASN1OctetString.getInstance(en.nextElement());
kemContext = null;
}

public KemOtherInfo(byte[] transactionID, byte[] kemContext) {
this.staticString = DEFAULT_staticString;
this.transactionID = new BEROctetString(transactionID);
this.kemContext = kemContext != null ? new BEROctetString(kemContext) : null;
}

private void addOptional(ASN1EncodableVector v, int tagNo, ASN1Encodable obj) {
Expand All @@ -129,24 +97,8 @@ private void addOptional(ASN1EncodableVector v, int tagNo, ASN1Encodable obj) {
}
}

public ASN1OctetString getCt() {
return ct;
}

public ASN1Integer getLen() {
return len;
}

public AlgorithmIdentifier getMac() {
return mac;
}

public ASN1OctetString getRecipNonce() {
return recipNonce;
}

public ASN1OctetString getSenderNonce() {
return senderNonce;
public ASN1OctetString getKemContext() {
return kemContext;
}

public ASN1OctetString getTransactionID() {
Expand All @@ -173,20 +125,14 @@ public ASN1Primitive toASN1Primitive() {
final ASN1EncodableVector v = new ASN1EncodableVector(7);

v.add(staticString);
addOptional(v, 0, transactionID);
addOptional(v, 1, senderNonce);
addOptional(v, 2, recipNonce);
v.add(len);
v.add(mac);
v.add(ct);

v.add(transactionID);
addOptional(v, 0, kemContext);
return new DERSequence(v);
}

@Override
public String toString() {
return "KemOtherInfo [\n\ttransactionID=" + transactionID
+ ", \n\tsenderNonce=" + senderNonce + ", \n\trecipNonce=" + recipNonce + ", \n\tlen=" + len
+ ", \n\tmac=" + mac.getAlgorithm() + ", \n\tct=" + ct + "]";
return "KemOtherInfo [staticString=" + staticString + ", transactionID=" + transactionID + ", kemContext="
+ kemContext + "]";
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -187,7 +187,7 @@ public static Provider getBouncyCastleProvider() {
* @return static certificate factory object
* @throws CertificateException thrown if the certificate factory could not be
* instantiated
* @throws Exception in case of an error
* @throws CertificateException in case of an internal error
*/
public static synchronized CertificateFactory getCertificateFactory() throws CertificateException {
if (certificateFactory == null) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,9 @@
import org.bouncycastle.crypto.SecretWithEncapsulation;
import org.bouncycastle.pqc.jcajce.provider.BouncyCastlePQCProvider;

/**
* top level wrapper for KEM algorithms
*/
public abstract class KemHandler {

protected static final SecureRandom RANDOMGENERATOR = new SecureRandom();
Expand All @@ -44,7 +47,12 @@ public abstract class KemHandler {
Security.addProvider(BC_PQ_PROV);
Security.addProvider(CertUtility.getBouncyCastleProvider());
}

/**
* create a handler for an specific algorithm
* @param kemAlgorithm the specific algorithm
* @return a handler for an specific algorithm
* @throws NoSuchAlgorithmException if kemAlgorithm is not supported
*/
public static KemHandler createKemHandler(String kemAlgorithm) throws NoSuchAlgorithmException {
if (ISOIECObjectIdentifiers.id_kem_rsa.getId().equalsIgnoreCase(kemAlgorithm)
|| "RSA".equalsIgnoreCase(kemAlgorithm)) {
Expand All @@ -69,8 +77,8 @@ public KemHandler(String kemAlgorithm, KeyPairGenerator kpg) {
* @param encapsulation cipher text
* @param priv private part of KEM keypair
* @return shared secret
* @throws InvalidAlgorithmParameterException
* @throws NoSuchAlgorithmException
* @throws InvalidAlgorithmParameterException if the private key is not sufficient
* @throws NoSuchAlgorithmException if the private key cannot be used by this {@link KemHandler}
*/
public abstract byte[] decapsulate(byte[] encapsulation, PrivateKey priv)
throws InvalidAlgorithmParameterException, NoSuchAlgorithmException;
Expand All @@ -80,9 +88,9 @@ public abstract byte[] decapsulate(byte[] encapsulation, PrivateKey priv)
*
* @param pub public part of KEM keypair
* @return shared secret and cipher text
* @throws InvalidAlgorithmParameterException
* @throws NoSuchAlgorithmException
* @throws NoSuchProviderException
* @throws InvalidAlgorithmParameterException if the public key is not sufficient
* @throws NoSuchAlgorithmException if the public key cannot be used by this {@link KemHandler}
* @throws NoSuchProviderException in case of intenal error
*/
public abstract SecretWithEncapsulation encapsulate(PublicKey pub)
throws InvalidAlgorithmParameterException, NoSuchAlgorithmException, NoSuchProviderException;
Expand All @@ -96,6 +104,11 @@ public KeyPair generateNewKeypair() {
return kpg.generateKeyPair();
}

/**
* get the AlgorithmIdentifier for this {@link KemHandler}
* @return the AlgorithmIdentifier
* @throws NoSuchAlgorithmException in case of internal error
*/
public AlgorithmIdentifier getAlgorithmIdentifier() throws NoSuchAlgorithmException {
return AlgorithmHelper.getKemAlgIdFromName(kemAlgorithm);
}
Expand Down
Loading

0 comments on commit f5706d9

Please sign in to comment.