package org.spongycastle.asn1.eac; import java.io.IOException; import org.spongycastle.asn1.ASN1EncodableVector; import org.spongycastle.asn1.ASN1InputStream; import org.spongycastle.asn1.ASN1Object; import org.spongycastle.asn1.ASN1Primitive; import org.spongycastle.asn1.BERTags; import org.spongycastle.asn1.DERApplicationSpecific; import org.spongycastle.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) { e.printStackTrace(); return null; } System.err.println("returning 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; } }