diff options
-rw-r--r-- | src/main/java/org/bouncycastle/eac/CertificateBody.java | 460 |
1 files changed, 460 insertions, 0 deletions
diff --git a/src/main/java/org/bouncycastle/eac/CertificateBody.java b/src/main/java/org/bouncycastle/eac/CertificateBody.java new file mode 100644 index 00000000..39443b0c --- /dev/null +++ b/src/main/java/org/bouncycastle/eac/CertificateBody.java @@ -0,0 +1,460 @@ +package org.bouncycastle.asn1.eac; + +import java.io.IOException; + +import org.bouncycastle.asn1.ASN1EncodableVector; +import org.bouncycastle.asn1.ASN1InputStream; +import org.bouncycastle.asn1.ASN1Object; +import org.bouncycastle.asn1.ASN1Primitive; +import org.bouncycastle.asn1.BERTags; +import org.bouncycastle.asn1.DERApplicationSpecific; +import org.bouncycastle.asn1.DEROctetString; + + +/** + * an Iso7816CertificateBody structure. + * <p/> + * <pre> + * CertificateBody ::= SEQUENCE { + * // version of the certificate format. Must be 0 (version 1) + * CertificateProfileIdentifer DERApplicationSpecific, + * //uniquely identifies the issuinng CA's signature key pair + * // contains the iso3166-1 alpha2 encoded country code, the + * // name of issuer and the sequence number of the key pair. + * CertificationAuthorityReference DERApplicationSpecific, + * // stores the encoded public key + * PublicKey Iso7816PublicKey, + * //associates the public key contained in the certificate with a unique name + * // contains the iso3166-1 alpha2 encoded country code, the + * // name of the holder and the sequence number of the key pair. + * certificateHolderReference DERApplicationSpecific, + * // Encodes the role of the holder (i.e. CVCA, DV, IS) and assigns read/write + * // access rights to data groups storing sensitive data + * certificateHolderAuthorization Iso7816CertificateHolderAuthorization, + * // the date of the certificate generation + * CertificateEffectiveDate DERApplicationSpecific, + * // the date after wich the certificate expires + * certificateExpirationDate DERApplicationSpecific + * } + * </pre> + */ +public class CertificateBody + extends ASN1Object +{ + ASN1InputStream seq; + private DERApplicationSpecific certificateProfileIdentifier;// version of the certificate format. Must be 0 (version 1) + private DERApplicationSpecific certificationAuthorityReference;//uniquely identifies the issuinng CA's signature key pair + private PublicKeyDataObject publicKey;// stores the encoded public key + private DERApplicationSpecific certificateHolderReference;//associates the public key contained in the certificate with a unique name + private CertificateHolderAuthorization certificateHolderAuthorization;// Encodes the role of the holder (i.e. CVCA, DV, IS) and assigns read/write access rights to data groups storing sensitive data + private DERApplicationSpecific certificateEffectiveDate;// the date of the certificate generation + private DERApplicationSpecific certificateExpirationDate;// the date after wich the certificate expires + private int certificateType = 0;// bit field of initialized data. This will tell us if the data are valid. + private static final int CPI = 0x01;//certificate Profile Identifier + private static final int CAR = 0x02;//certification Authority Reference + private static final int PK = 0x04;//public Key + private static final int CHR = 0x08;//certificate Holder Reference + private static final int CHA = 0x10;//certificate Holder Authorization + private static final int CEfD = 0x20;//certificate Effective Date + private static final int CExD = 0x40;//certificate Expiration Date + + public static final int profileType = 0x7f;//Profile type Certificate + public static final int requestType = 0x0D;// Request type Certificate + + private void setIso7816CertificateBody(DERApplicationSpecific appSpe) + throws IOException + { + byte[] content; + if (appSpe.getApplicationTag() == EACTags.CERTIFICATE_CONTENT_TEMPLATE) + { + content = appSpe.getContents(); + } + else + { + throw new IOException("Bad tag : not an iso7816 CERTIFICATE_CONTENT_TEMPLATE"); + } + ASN1InputStream aIS = new ASN1InputStream(content); + ASN1Primitive obj; + while ((obj = aIS.readObject()) != null) + { + DERApplicationSpecific aSpe; + + if (obj instanceof DERApplicationSpecific) + { + aSpe = (DERApplicationSpecific)obj; + } + else + { + throw new IOException("Not a valid iso7816 content : not a DERApplicationSpecific Object :" + EACTags.encodeTag(appSpe) + obj.getClass()); + } + switch (aSpe.getApplicationTag()) + { + case EACTags.INTERCHANGE_PROFILE: + setCertificateProfileIdentifier(aSpe); + break; + case EACTags.ISSUER_IDENTIFICATION_NUMBER: + setCertificationAuthorityReference(aSpe); + break; + case EACTags.CARDHOLDER_PUBLIC_KEY_TEMPLATE: + setPublicKey(PublicKeyDataObject.getInstance(aSpe.getObject(BERTags.SEQUENCE))); + break; + case EACTags.CARDHOLDER_NAME: + setCertificateHolderReference(aSpe); + break; + case EACTags.CERTIFICATE_HOLDER_AUTHORIZATION_TEMPLATE: + setCertificateHolderAuthorization(new CertificateHolderAuthorization(aSpe)); + break; + case EACTags.APPLICATION_EFFECTIVE_DATE: + setCertificateEffectiveDate(aSpe); + break; + case EACTags.APPLICATION_EXPIRATION_DATE: + setCertificateExpirationDate(aSpe); + break; + default: + certificateType = 0; + throw new IOException("Not a valid iso7816 DERApplicationSpecific tag " + aSpe.getApplicationTag()); + } + } + } + + /** + * builds an Iso7816CertificateBody by settings each parameters. + * + * @param certificateProfileIdentifier + * @param certificationAuthorityReference + * + * @param publicKey + * @param certificateHolderReference + * @param certificateHolderAuthorization + * @param certificateEffectiveDate + * @param certificateExpirationDate + * @throws IOException + */ + public CertificateBody( + DERApplicationSpecific certificateProfileIdentifier, + CertificationAuthorityReference certificationAuthorityReference, + PublicKeyDataObject publicKey, + CertificateHolderReference certificateHolderReference, + CertificateHolderAuthorization certificateHolderAuthorization, + PackedDate certificateEffectiveDate, + PackedDate certificateExpirationDate + ) + { + setCertificateProfileIdentifier(certificateProfileIdentifier); + setCertificationAuthorityReference(new DERApplicationSpecific( + EACTags.ISSUER_IDENTIFICATION_NUMBER, certificationAuthorityReference.getEncoded())); + setPublicKey(publicKey); + setCertificateHolderReference(new DERApplicationSpecific( + EACTags.CARDHOLDER_NAME, certificateHolderReference.getEncoded())); + setCertificateHolderAuthorization(certificateHolderAuthorization); + try + { + setCertificateEffectiveDate(new DERApplicationSpecific( + false, EACTags.APPLICATION_EFFECTIVE_DATE, new DEROctetString(certificateEffectiveDate.getEncoding()))); + setCertificateExpirationDate(new DERApplicationSpecific( + false, EACTags.APPLICATION_EXPIRATION_DATE, new DEROctetString(certificateExpirationDate.getEncoding()))); + } + catch (IOException e) + { + throw new IllegalArgumentException("unable to encode dates: " + e.getMessage()); + } + } + + /** + * builds an Iso7816CertificateBody with an ASN1InputStream. + * + * @param obj DERApplicationSpecific containing the whole body. + * @throws IOException if the body is not valid. + */ + private CertificateBody(DERApplicationSpecific obj) + throws IOException + { + setIso7816CertificateBody(obj); + } + + /** + * create a profile type Iso7816CertificateBody. + * + * @return return the "profile" type certificate body. + * @throws IOException if the DERApplicationSpecific cannot be created. + */ + private ASN1Primitive profileToASN1Object() + throws IOException + { + ASN1EncodableVector v = new ASN1EncodableVector(); + + v.add(certificateProfileIdentifier); + v.add(certificationAuthorityReference); + v.add(new DERApplicationSpecific(false, EACTags.CARDHOLDER_PUBLIC_KEY_TEMPLATE, publicKey)); + v.add(certificateHolderReference); + v.add(certificateHolderAuthorization); + v.add(certificateEffectiveDate); + v.add(certificateExpirationDate); + return new DERApplicationSpecific(EACTags.CERTIFICATE_CONTENT_TEMPLATE, v); + } + + private void setCertificateProfileIdentifier(DERApplicationSpecific certificateProfileIdentifier) + throws IllegalArgumentException { + if (certificateProfileIdentifier.getApplicationTag() == EACTags.INTERCHANGE_PROFILE) { + this.certificateProfileIdentifier = certificateProfileIdentifier; + certificateType |= CPI; + } + else + throw new IllegalArgumentException("Not an Iso7816Tags.INTERCHANGE_PROFILE tag :"+ EACTags.encodeTag(certificateProfileIdentifier)); + } + + private void setCertificateHolderReference(DERApplicationSpecific certificateHolderReference) + throws IllegalArgumentException { + if (certificateHolderReference.getApplicationTag() == EACTags.CARDHOLDER_NAME) { + this.certificateHolderReference = certificateHolderReference; + certificateType |= CHR; + } + else + throw new IllegalArgumentException("Not an Iso7816Tags.CARDHOLDER_NAME tag"); + } + + /** + * set the CertificationAuthorityReference. + * @param certificationAuthorityReference the DERApplicationSpecific containing the CertificationAuthorityReference. + * @throws IllegalArgumentException if the DERApplicationSpecific is not valid. + */ + private void setCertificationAuthorityReference( + DERApplicationSpecific certificationAuthorityReference) + throws IllegalArgumentException { + if (certificationAuthorityReference.getApplicationTag() == EACTags.ISSUER_IDENTIFICATION_NUMBER) { + this.certificationAuthorityReference = certificationAuthorityReference; + certificateType |= CAR; + } + else + throw new IllegalArgumentException("Not an Iso7816Tags.ISSUER_IDENTIFICATION_NUMBER tag"); + } + + /** + * set the public Key + * @param publicKey : the DERApplicationSpecific containing the public key + * @throws java.io.IOException + */ + private void setPublicKey(PublicKeyDataObject publicKey) + { + this.publicKey = PublicKeyDataObject.getInstance(publicKey); + this.certificateType |= PK; + } + + /** + * create a request type Iso7816CertificateBody. + * + * @return return the "request" type certificate body. + * @throws IOException if the DERApplicationSpecific cannot be created. + */ + private ASN1Primitive requestToASN1Object() + throws IOException + { + ASN1EncodableVector v = new ASN1EncodableVector(); + + v.add(certificateProfileIdentifier); + v.add(new DERApplicationSpecific(false, EACTags.CARDHOLDER_PUBLIC_KEY_TEMPLATE, publicKey)); + v.add(certificateHolderReference); + return new DERApplicationSpecific(EACTags.CERTIFICATE_CONTENT_TEMPLATE, v); + } + + /** + * create a "request" or "profile" type Iso7816CertificateBody according to the variables sets. + * + * @return return the ASN1Primitive representing the "request" or "profile" type certificate body. + * @throws IOException if the DERApplicationSpecific cannot be created or if data are missings to create a valid certificate. + */ + public ASN1Primitive toASN1Primitive() + { + try + { + if (certificateType == profileType) + { + return profileToASN1Object(); + } + if (certificateType == requestType) + { + return requestToASN1Object(); + } + } + catch (IOException e) + { + return null; + } + return null; + } + + /** + * gives the type of the certificate (value should be profileType or requestType if all data are set). + * + * @return the int representing the data already set. + */ + public int getCertificateType() + { + return certificateType; + } + + /** + * Gives an instance of Iso7816CertificateBody taken from Object obj + * + * @param obj is the Object to extract the certificate body from. + * @return the Iso7816CertificateBody taken from Object obj. + * @throws IOException if object is not valid. + */ + public static CertificateBody getInstance(Object obj) + throws IOException + { + if (obj instanceof CertificateBody) + { + return (CertificateBody)obj; + } + else if (obj != null) + { + return new CertificateBody(DERApplicationSpecific.getInstance(obj)); + } + + return null; + } + + /** + * @return the date of the certificate generation + */ + public PackedDate getCertificateEffectiveDate() + { + if ((this.certificateType & CertificateBody.CEfD) == + CertificateBody.CEfD) + { + return new PackedDate(certificateEffectiveDate.getContents()); + } + return null; + } + + /** + * set the date of the certificate generation + * + * @param ced DERApplicationSpecific containing the date of the certificate generation + * @throws IllegalArgumentException if the tag is not Iso7816Tags.APPLICATION_EFFECTIVE_DATE + */ + private void setCertificateEffectiveDate(DERApplicationSpecific ced) + throws IllegalArgumentException + { + if (ced.getApplicationTag() == EACTags.APPLICATION_EFFECTIVE_DATE) + { + this.certificateEffectiveDate = ced; + certificateType |= CEfD; + } + else + { + throw new IllegalArgumentException("Not an Iso7816Tags.APPLICATION_EFFECTIVE_DATE tag :" + EACTags.encodeTag(ced)); + } + } + + /** + * @return the date after wich the certificate expires + */ + public PackedDate getCertificateExpirationDate() + throws IOException + { + if ((this.certificateType & CertificateBody.CExD) == + CertificateBody.CExD) + { + return new PackedDate(certificateExpirationDate.getContents()); + } + throw new IOException("certificate Expiration Date not set"); + } + + /** + * set the date after wich the certificate expires + * + * @param ced DERApplicationSpecific containing the date after wich the certificate expires + * @throws IllegalArgumentException if the tag is not Iso7816Tags.APPLICATION_EXPIRATION_DATE + */ + private void setCertificateExpirationDate(DERApplicationSpecific ced) + throws IllegalArgumentException + { + if (ced.getApplicationTag() == EACTags.APPLICATION_EXPIRATION_DATE) + { + this.certificateExpirationDate = ced; + certificateType |= CExD; + } + else + { + throw new IllegalArgumentException("Not an Iso7816Tags.APPLICATION_EXPIRATION_DATE tag"); + } + } + + /** + * the Iso7816CertificateHolderAuthorization encodes the role of the holder + * (i.e. CVCA, DV, IS) and assigns read/write access rights to data groups + * storing sensitive data. This functions returns the Certificate Holder + * Authorization + * + * @return the Iso7816CertificateHolderAuthorization + */ + public CertificateHolderAuthorization getCertificateHolderAuthorization() + throws IOException + { + if ((this.certificateType & CertificateBody.CHA) == + CertificateBody.CHA) + { + return certificateHolderAuthorization; + } + throw new IOException("Certificate Holder Authorisation not set"); + } + + /** + * set the CertificateHolderAuthorization + * + * @param cha the Certificate Holder Authorization + */ + private void setCertificateHolderAuthorization( + CertificateHolderAuthorization cha) + { + this.certificateHolderAuthorization = cha; + certificateType |= CHA; + } + + /** + * certificateHolderReference : associates the public key contained in the certificate with a unique name + * + * @return the certificateHolderReference. + */ + public CertificateHolderReference getCertificateHolderReference() + { + return new CertificateHolderReference(certificateHolderReference.getContents()); + } + + /** + * CertificateProfileIdentifier : version of the certificate format. Must be 0 (version 1) + * + * @return the CertificateProfileIdentifier + */ + public DERApplicationSpecific getCertificateProfileIdentifier() + { + return certificateProfileIdentifier; + } + + /** + * get the certificationAuthorityReference + * certificationAuthorityReference : uniquely identifies the issuinng CA's signature key pair + * + * @return the certificationAuthorityReference + */ + public CertificationAuthorityReference getCertificationAuthorityReference() + throws IOException + { + if ((this.certificateType & CertificateBody.CAR) == + CertificateBody.CAR) + { + return new CertificationAuthorityReference(certificationAuthorityReference.getContents()); + } + throw new IOException("Certification authority reference not set"); + } + + /** + * @return the PublicKey + */ + public PublicKeyDataObject getPublicKey() + { + return publicKey; + } +} |