diff options
Diffstat (limited to 'core/src/main/java/org/bouncycastle/asn1/icao')
5 files changed, 478 insertions, 0 deletions
diff --git a/core/src/main/java/org/bouncycastle/asn1/icao/CscaMasterList.java b/core/src/main/java/org/bouncycastle/asn1/icao/CscaMasterList.java new file mode 100644 index 00000000..2cae261f --- /dev/null +++ b/core/src/main/java/org/bouncycastle/asn1/icao/CscaMasterList.java @@ -0,0 +1,114 @@ +package org.bouncycastle.asn1.icao; + +import org.bouncycastle.asn1.ASN1EncodableVector; +import org.bouncycastle.asn1.ASN1Integer; +import org.bouncycastle.asn1.ASN1Object; +import org.bouncycastle.asn1.ASN1Primitive; +import org.bouncycastle.asn1.ASN1Sequence; +import org.bouncycastle.asn1.ASN1Set; +import org.bouncycastle.asn1.DERSequence; +import org.bouncycastle.asn1.DERSet; +import org.bouncycastle.asn1.x509.Certificate; + +/** + * The CscaMasterList object. This object can be wrapped in a + * CMSSignedData to be published in LDAP. + * <p/> + * <pre> + * CscaMasterList ::= SEQUENCE { + * version CscaMasterListVersion, + * certList SET OF Certificate } + * + * CscaMasterListVersion :: INTEGER {v0(0)} + * </pre> + */ + +public class CscaMasterList + extends ASN1Object +{ + private ASN1Integer version = new ASN1Integer(0); + private Certificate[] certList; + + public static CscaMasterList getInstance( + Object obj) + { + if (obj instanceof CscaMasterList) + { + return (CscaMasterList)obj; + } + else if (obj != null) + { + return new CscaMasterList(ASN1Sequence.getInstance(obj)); + } + + return null; + } + + private CscaMasterList( + ASN1Sequence seq) + { + if (seq == null || seq.size() == 0) + { + throw new IllegalArgumentException( + "null or empty sequence passed."); + } + if (seq.size() != 2) + { + throw new IllegalArgumentException( + "Incorrect sequence size: " + seq.size()); + } + + version = ASN1Integer.getInstance(seq.getObjectAt(0)); + ASN1Set certSet = ASN1Set.getInstance(seq.getObjectAt(1)); + certList = new Certificate[certSet.size()]; + for (int i = 0; i < certList.length; i++) + { + certList[i] + = Certificate.getInstance(certSet.getObjectAt(i)); + } + } + + public CscaMasterList( + Certificate[] certStructs) + { + certList = copyCertList(certStructs); + } + + public int getVersion() + { + return version.getValue().intValue(); + } + + public Certificate[] getCertStructs() + { + return copyCertList(certList); + } + + private Certificate[] copyCertList(Certificate[] orig) + { + Certificate[] certs = new Certificate[orig.length]; + + for (int i = 0; i != certs.length; i++) + { + certs[i] = orig[i]; + } + + return certs; + } + + public ASN1Primitive toASN1Primitive() + { + ASN1EncodableVector seq = new ASN1EncodableVector(); + + seq.add(version); + + ASN1EncodableVector certSet = new ASN1EncodableVector(); + for (int i = 0; i < certList.length; i++) + { + certSet.add(certList[i]); + } + seq.add(new DERSet(certSet)); + + return new DERSequence(seq); + } +} diff --git a/core/src/main/java/org/bouncycastle/asn1/icao/DataGroupHash.java b/core/src/main/java/org/bouncycastle/asn1/icao/DataGroupHash.java new file mode 100644 index 00000000..b4c4c5c8 --- /dev/null +++ b/core/src/main/java/org/bouncycastle/asn1/icao/DataGroupHash.java @@ -0,0 +1,97 @@ +package org.bouncycastle.asn1.icao; + +import java.util.Enumeration; + +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.DERSequence; + +/** + * The DataGroupHash object. + * <pre> + * DataGroupHash ::= SEQUENCE { + * dataGroupNumber DataGroupNumber, + * dataGroupHashValue OCTET STRING } + * + * DataGroupNumber ::= INTEGER { + * dataGroup1 (1), + * dataGroup1 (2), + * dataGroup1 (3), + * dataGroup1 (4), + * dataGroup1 (5), + * dataGroup1 (6), + * dataGroup1 (7), + * dataGroup1 (8), + * dataGroup1 (9), + * dataGroup1 (10), + * dataGroup1 (11), + * dataGroup1 (12), + * dataGroup1 (13), + * dataGroup1 (14), + * dataGroup1 (15), + * dataGroup1 (16) } + * + * </pre> + */ +public class DataGroupHash + extends ASN1Object +{ + ASN1Integer dataGroupNumber; + ASN1OctetString dataGroupHashValue; + + public static DataGroupHash getInstance( + Object obj) + { + if (obj instanceof DataGroupHash) + { + return (DataGroupHash)obj; + } + else if (obj != null) + { + return new DataGroupHash(ASN1Sequence.getInstance(obj)); + } + + return null; + } + + private DataGroupHash(ASN1Sequence seq) + { + Enumeration e = seq.getObjects(); + + // dataGroupNumber + dataGroupNumber = ASN1Integer.getInstance(e.nextElement()); + // dataGroupHashValue + dataGroupHashValue = ASN1OctetString.getInstance(e.nextElement()); + } + + public DataGroupHash( + int dataGroupNumber, + ASN1OctetString dataGroupHashValue) + { + this.dataGroupNumber = new ASN1Integer(dataGroupNumber); + this.dataGroupHashValue = dataGroupHashValue; + } + + public int getDataGroupNumber() + { + return dataGroupNumber.getValue().intValue(); + } + + public ASN1OctetString getDataGroupHashValue() + { + return dataGroupHashValue; + } + + public ASN1Primitive toASN1Primitive() + { + ASN1EncodableVector seq = new ASN1EncodableVector(); + seq.add(dataGroupNumber); + seq.add(dataGroupHashValue); + + return new DERSequence(seq); + } +} diff --git a/core/src/main/java/org/bouncycastle/asn1/icao/ICAOObjectIdentifiers.java b/core/src/main/java/org/bouncycastle/asn1/icao/ICAOObjectIdentifiers.java new file mode 100644 index 00000000..0b5da2be --- /dev/null +++ b/core/src/main/java/org/bouncycastle/asn1/icao/ICAOObjectIdentifiers.java @@ -0,0 +1,33 @@ +package org.bouncycastle.asn1.icao; + +import org.bouncycastle.asn1.ASN1ObjectIdentifier; + +public interface ICAOObjectIdentifiers +{ + // + // base id + // + static final ASN1ObjectIdentifier id_icao = new ASN1ObjectIdentifier("2.23.136"); + + static final ASN1ObjectIdentifier id_icao_mrtd = id_icao.branch("1"); + static final ASN1ObjectIdentifier id_icao_mrtd_security = id_icao_mrtd.branch("1"); + + // LDS security object, see ICAO Doc 9303-Volume 2-Section IV-A3.2 + static final ASN1ObjectIdentifier id_icao_ldsSecurityObject = id_icao_mrtd_security.branch("1"); + + // CSCA master list, see TR CSCA Countersigning and Master List issuance + static final ASN1ObjectIdentifier id_icao_cscaMasterList = id_icao_mrtd_security.branch("2"); + static final ASN1ObjectIdentifier id_icao_cscaMasterListSigningKey = id_icao_mrtd_security.branch("3"); + + // document type list, see draft TR LDS and PKI Maintenance, par. 3.2.1 + static final ASN1ObjectIdentifier id_icao_documentTypeList = id_icao_mrtd_security.branch("4"); + + // Active Authentication protocol, see draft TR LDS and PKI Maintenance, + // par. 5.2.2 + static final ASN1ObjectIdentifier id_icao_aaProtocolObject = id_icao_mrtd_security.branch("5"); + + // CSCA name change and key reoll-over, see draft TR LDS and PKI + // Maintenance, par. 3.2.1 + static final ASN1ObjectIdentifier id_icao_extensions = id_icao_mrtd_security.branch("6"); + static final ASN1ObjectIdentifier id_icao_extensions_namechangekeyrollover = id_icao_extensions.branch("1"); +} diff --git a/core/src/main/java/org/bouncycastle/asn1/icao/LDSSecurityObject.java b/core/src/main/java/org/bouncycastle/asn1/icao/LDSSecurityObject.java new file mode 100644 index 00000000..fae8762b --- /dev/null +++ b/core/src/main/java/org/bouncycastle/asn1/icao/LDSSecurityObject.java @@ -0,0 +1,159 @@ +package org.bouncycastle.asn1.icao; + +import java.util.Enumeration; + +import org.bouncycastle.asn1.ASN1EncodableVector; +import org.bouncycastle.asn1.ASN1Integer; +import org.bouncycastle.asn1.ASN1Object; +import org.bouncycastle.asn1.ASN1Primitive; +import org.bouncycastle.asn1.ASN1Sequence; +import org.bouncycastle.asn1.DERSequence; +import org.bouncycastle.asn1.x509.AlgorithmIdentifier; + +/** + * The LDSSecurityObject object (V1.8). + * <pre> + * LDSSecurityObject ::= SEQUENCE { + * version LDSSecurityObjectVersion, + * hashAlgorithm DigestAlgorithmIdentifier, + * dataGroupHashValues SEQUENCE SIZE (2..ub-DataGroups) OF DataHashGroup, + * ldsVersionInfo LDSVersionInfo OPTIONAL + * -- if present, version MUST be v1 } + * + * DigestAlgorithmIdentifier ::= AlgorithmIdentifier, + * + * LDSSecurityObjectVersion :: INTEGER {V0(0)} + * </pre> + */ + +public class LDSSecurityObject + extends ASN1Object + implements ICAOObjectIdentifiers +{ + public static final int ub_DataGroups = 16; + + private ASN1Integer version = new ASN1Integer(0); + private AlgorithmIdentifier digestAlgorithmIdentifier; + private DataGroupHash[] datagroupHash; + private LDSVersionInfo versionInfo; + + public static LDSSecurityObject getInstance( + Object obj) + { + if (obj instanceof LDSSecurityObject) + { + return (LDSSecurityObject)obj; + } + else if (obj != null) + { + return new LDSSecurityObject(ASN1Sequence.getInstance(obj)); + } + + return null; + } + + private LDSSecurityObject( + ASN1Sequence seq) + { + if (seq == null || seq.size() == 0) + { + throw new IllegalArgumentException("null or empty sequence passed."); + } + + Enumeration e = seq.getObjects(); + + // version + version = ASN1Integer.getInstance(e.nextElement()); + // digestAlgorithmIdentifier + digestAlgorithmIdentifier = AlgorithmIdentifier.getInstance(e.nextElement()); + + ASN1Sequence datagroupHashSeq = ASN1Sequence.getInstance(e.nextElement()); + + if (version.getValue().intValue() == 1) + { + versionInfo = LDSVersionInfo.getInstance(e.nextElement()); + } + + checkDatagroupHashSeqSize(datagroupHashSeq.size()); + + datagroupHash = new DataGroupHash[datagroupHashSeq.size()]; + for (int i= 0; i< datagroupHashSeq.size();i++) + { + datagroupHash[i] = DataGroupHash.getInstance(datagroupHashSeq.getObjectAt(i)); + } + } + + public LDSSecurityObject( + AlgorithmIdentifier digestAlgorithmIdentifier, + DataGroupHash[] datagroupHash) + { + this.version = new ASN1Integer(0); + this.digestAlgorithmIdentifier = digestAlgorithmIdentifier; + this.datagroupHash = datagroupHash; + + checkDatagroupHashSeqSize(datagroupHash.length); + } + + public LDSSecurityObject( + AlgorithmIdentifier digestAlgorithmIdentifier, + DataGroupHash[] datagroupHash, + LDSVersionInfo versionInfo) + { + this.version = new ASN1Integer(1); + this.digestAlgorithmIdentifier = digestAlgorithmIdentifier; + this.datagroupHash = datagroupHash; + this.versionInfo = versionInfo; + + checkDatagroupHashSeqSize(datagroupHash.length); + } + + private void checkDatagroupHashSeqSize(int size) + { + if ((size < 2) || (size > ub_DataGroups)) + { + throw new IllegalArgumentException("wrong size in DataGroupHashValues : not in (2.."+ ub_DataGroups +")"); + } + } + + public int getVersion() + { + return version.getValue().intValue(); + } + + public AlgorithmIdentifier getDigestAlgorithmIdentifier() + { + return digestAlgorithmIdentifier; + } + + public DataGroupHash[] getDatagroupHash() + { + return datagroupHash; + } + + public LDSVersionInfo getVersionInfo() + { + return versionInfo; + } + + public ASN1Primitive toASN1Primitive() + { + ASN1EncodableVector seq = new ASN1EncodableVector(); + + seq.add(version); + seq.add(digestAlgorithmIdentifier); + + ASN1EncodableVector seqname = new ASN1EncodableVector(); + for (int i = 0; i < datagroupHash.length; i++) + { + seqname.add(datagroupHash[i]); + } + seq.add(new DERSequence(seqname)); + + if (versionInfo != null) + { + seq.add(versionInfo); + } + + return new DERSequence(seq); + } +} diff --git a/core/src/main/java/org/bouncycastle/asn1/icao/LDSVersionInfo.java b/core/src/main/java/org/bouncycastle/asn1/icao/LDSVersionInfo.java new file mode 100644 index 00000000..9c5ae336 --- /dev/null +++ b/core/src/main/java/org/bouncycastle/asn1/icao/LDSVersionInfo.java @@ -0,0 +1,75 @@ +package org.bouncycastle.asn1.icao; + +import org.bouncycastle.asn1.ASN1EncodableVector; +import org.bouncycastle.asn1.ASN1Object; +import org.bouncycastle.asn1.ASN1Primitive; +import org.bouncycastle.asn1.ASN1Sequence; +import org.bouncycastle.asn1.DERPrintableString; +import org.bouncycastle.asn1.DERSequence; + +public class LDSVersionInfo + extends ASN1Object +{ + private DERPrintableString ldsVersion; + private DERPrintableString unicodeVersion; + + public LDSVersionInfo(String ldsVersion, String unicodeVersion) + { + this.ldsVersion = new DERPrintableString(ldsVersion); + this.unicodeVersion = new DERPrintableString(unicodeVersion); + } + + private LDSVersionInfo(ASN1Sequence seq) + { + if (seq.size() != 2) + { + throw new IllegalArgumentException("sequence wrong size for LDSVersionInfo"); + } + + this.ldsVersion = DERPrintableString.getInstance(seq.getObjectAt(0)); + this.unicodeVersion = DERPrintableString.getInstance(seq.getObjectAt(1)); + } + + public static LDSVersionInfo getInstance(Object obj) + { + if (obj instanceof LDSVersionInfo) + { + return (LDSVersionInfo)obj; + } + else if (obj != null) + { + return new LDSVersionInfo(ASN1Sequence.getInstance(obj)); + } + + return null; + } + + public String getLdsVersion() + { + return ldsVersion.getString(); + } + + public String getUnicodeVersion() + { + return unicodeVersion.getString(); + } + + /** + * <pre> + * LDSVersionInfo ::= SEQUENCE { + * ldsVersion PRINTABLE STRING + * unicodeVersion PRINTABLE STRING + * } + * </pre> + * @return + */ + public ASN1Primitive toASN1Primitive() + { + ASN1EncodableVector v = new ASN1EncodableVector(); + + v.add(ldsVersion); + v.add(unicodeVersion); + + return new DERSequence(v); + } +} |