001package org.apache.commons.ssl.org.bouncycastle.asn1.eac;
002
003import java.io.IOException;
004
005import org.apache.commons.ssl.org.bouncycastle.asn1.ASN1EncodableVector;
006import org.apache.commons.ssl.org.bouncycastle.asn1.ASN1InputStream;
007import org.apache.commons.ssl.org.bouncycastle.asn1.ASN1Object;
008import org.apache.commons.ssl.org.bouncycastle.asn1.ASN1Primitive;
009import org.apache.commons.ssl.org.bouncycastle.asn1.BERTags;
010import org.apache.commons.ssl.org.bouncycastle.asn1.DERApplicationSpecific;
011import org.apache.commons.ssl.org.bouncycastle.asn1.DEROctetString;
012
013
014/**
015 * an Iso7816CertificateBody structure.
016 * <pre>
017 *  CertificateBody ::= SEQUENCE {
018 *      // version of the certificate format. Must be 0 (version 1)
019 *      CertificateProfileIdentifer         DERApplicationSpecific,
020 *      //uniquely identifies the issuinng CA's signature key pair
021 *      // contains the iso3166-1 alpha2 encoded country code, the
022 *      // name of issuer and the sequence number of the key pair.
023 *      CertificationAuthorityReference        DERApplicationSpecific,
024 *      // stores the encoded public key
025 *      PublicKey                            Iso7816PublicKey,
026 *      //associates the public key contained in the certificate with a unique name
027 *      // contains the iso3166-1 alpha2 encoded country code, the
028 *      // name of the holder and the sequence number of the key pair.
029 *      certificateHolderReference            DERApplicationSpecific,
030 *      // Encodes the role of the holder (i.e. CVCA, DV, IS) and assigns read/write
031 *      // access rights to data groups storing sensitive data
032 *      certificateHolderAuthorization        Iso7816CertificateHolderAuthorization,
033 *      // the date of the certificate generation
034 *      CertificateEffectiveDate            DERApplicationSpecific,
035 *      // the date after wich the certificate expires
036 *      certificateExpirationDate            DERApplicationSpecific
037 *  }
038 * </pre>
039 */
040public class CertificateBody
041    extends ASN1Object
042{
043    ASN1InputStream seq;
044    private DERApplicationSpecific certificateProfileIdentifier;// version of the certificate format. Must be 0 (version 1)
045    private DERApplicationSpecific certificationAuthorityReference;//uniquely identifies the issuinng CA's signature key pair
046    private PublicKeyDataObject publicKey;// stores the encoded public key
047    private DERApplicationSpecific certificateHolderReference;//associates the public key contained in the certificate with a unique name
048    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
049    private DERApplicationSpecific certificateEffectiveDate;// the date of the certificate generation
050    private DERApplicationSpecific certificateExpirationDate;// the date after wich the certificate expires
051    private int certificateType = 0;// bit field of initialized data. This will tell us if the data are valid.
052    private static final int CPI = 0x01;//certificate Profile Identifier
053    private static final int CAR = 0x02;//certification Authority Reference
054    private static final int PK = 0x04;//public Key
055    private static final int CHR = 0x08;//certificate Holder Reference
056    private static final int CHA = 0x10;//certificate Holder Authorization
057    private static final int CEfD = 0x20;//certificate Effective Date
058    private static final int CExD = 0x40;//certificate Expiration Date
059
060    public static final int profileType = 0x7f;//Profile type Certificate
061    public static final int requestType = 0x0D;// Request type Certificate
062
063    private void setIso7816CertificateBody(DERApplicationSpecific appSpe)
064        throws IOException
065    {
066        byte[] content;
067        if (appSpe.getApplicationTag() == EACTags.CERTIFICATE_CONTENT_TEMPLATE)
068        {
069            content = appSpe.getContents();
070        }
071        else
072        {
073            throw new IOException("Bad tag : not an iso7816 CERTIFICATE_CONTENT_TEMPLATE");
074        }
075        ASN1InputStream aIS = new ASN1InputStream(content);
076        ASN1Primitive obj;
077        while ((obj = aIS.readObject()) != null)
078        {
079            DERApplicationSpecific aSpe;
080
081            if (obj instanceof DERApplicationSpecific)
082            {
083                aSpe = (DERApplicationSpecific)obj;
084            }
085            else
086            {
087                throw new IOException("Not a valid iso7816 content : not a DERApplicationSpecific Object :" + EACTags.encodeTag(appSpe) + obj.getClass());
088            }
089            switch (aSpe.getApplicationTag())
090            {
091            case EACTags.INTERCHANGE_PROFILE:
092                setCertificateProfileIdentifier(aSpe);
093                break;
094            case EACTags.ISSUER_IDENTIFICATION_NUMBER:
095                setCertificationAuthorityReference(aSpe);
096                break;
097            case EACTags.CARDHOLDER_PUBLIC_KEY_TEMPLATE:
098                setPublicKey(PublicKeyDataObject.getInstance(aSpe.getObject(BERTags.SEQUENCE)));
099                break;
100            case EACTags.CARDHOLDER_NAME:
101                setCertificateHolderReference(aSpe);
102                break;
103            case EACTags.CERTIFICATE_HOLDER_AUTHORIZATION_TEMPLATE:
104                setCertificateHolderAuthorization(new CertificateHolderAuthorization(aSpe));
105                break;
106            case EACTags.APPLICATION_EFFECTIVE_DATE:
107                setCertificateEffectiveDate(aSpe);
108                break;
109            case EACTags.APPLICATION_EXPIRATION_DATE:
110                setCertificateExpirationDate(aSpe);
111                break;
112            default:
113                certificateType = 0;
114                throw new IOException("Not a valid iso7816 DERApplicationSpecific tag " + aSpe.getApplicationTag());
115            }
116        }
117    }
118
119    /**
120     * builds an Iso7816CertificateBody by settings each parameters.
121     *
122     * @param certificateProfileIdentifier
123     * @param certificationAuthorityReference
124     *
125     * @param publicKey
126     * @param certificateHolderReference
127     * @param certificateHolderAuthorization
128     * @param certificateEffectiveDate
129     * @param certificateExpirationDate
130     */
131    public CertificateBody(
132        DERApplicationSpecific certificateProfileIdentifier,
133        CertificationAuthorityReference certificationAuthorityReference,
134        PublicKeyDataObject publicKey,
135        CertificateHolderReference certificateHolderReference,
136        CertificateHolderAuthorization certificateHolderAuthorization,
137        PackedDate certificateEffectiveDate,
138        PackedDate certificateExpirationDate
139    )
140    {
141        setCertificateProfileIdentifier(certificateProfileIdentifier);
142        setCertificationAuthorityReference(new DERApplicationSpecific(
143            EACTags.ISSUER_IDENTIFICATION_NUMBER, certificationAuthorityReference.getEncoded()));
144        setPublicKey(publicKey);
145        setCertificateHolderReference(new DERApplicationSpecific(
146            EACTags.CARDHOLDER_NAME, certificateHolderReference.getEncoded()));
147        setCertificateHolderAuthorization(certificateHolderAuthorization);
148        try
149        {
150            setCertificateEffectiveDate(new DERApplicationSpecific(
151                false, EACTags.APPLICATION_EFFECTIVE_DATE, new DEROctetString(certificateEffectiveDate.getEncoding())));
152            setCertificateExpirationDate(new DERApplicationSpecific(
153                false, EACTags.APPLICATION_EXPIRATION_DATE, new DEROctetString(certificateExpirationDate.getEncoding())));
154        }
155        catch (IOException e)
156        {
157            throw new IllegalArgumentException("unable to encode dates: " + e.getMessage());
158        }
159    }
160
161    /**
162     * builds an Iso7816CertificateBody with an ASN1InputStream.
163     *
164     * @param obj DERApplicationSpecific containing the whole body.
165     * @throws IOException if the body is not valid.
166     */
167    private CertificateBody(DERApplicationSpecific obj)
168        throws IOException
169    {
170        setIso7816CertificateBody(obj);
171    }
172
173    /**
174     * create a profile type Iso7816CertificateBody.
175     *
176     * @return return the "profile" type certificate body.
177     * @throws IOException if the DERApplicationSpecific cannot be created.
178     */
179    private ASN1Primitive profileToASN1Object()
180        throws IOException
181    {
182        ASN1EncodableVector v = new ASN1EncodableVector();
183
184        v.add(certificateProfileIdentifier);
185        v.add(certificationAuthorityReference);
186        v.add(new DERApplicationSpecific(false, EACTags.CARDHOLDER_PUBLIC_KEY_TEMPLATE, publicKey));
187        v.add(certificateHolderReference);
188        v.add(certificateHolderAuthorization);
189        v.add(certificateEffectiveDate);
190        v.add(certificateExpirationDate);
191        return new DERApplicationSpecific(EACTags.CERTIFICATE_CONTENT_TEMPLATE, v);
192    }
193
194    private void setCertificateProfileIdentifier(DERApplicationSpecific certificateProfileIdentifier)
195        throws IllegalArgumentException
196    {
197        if (certificateProfileIdentifier.getApplicationTag() == EACTags.INTERCHANGE_PROFILE)
198        {
199            this.certificateProfileIdentifier = certificateProfileIdentifier;
200            certificateType |= CPI;
201        }
202        else
203        {
204            throw new IllegalArgumentException("Not an Iso7816Tags.INTERCHANGE_PROFILE tag :" + EACTags.encodeTag(certificateProfileIdentifier));
205        }
206    }
207
208    private void setCertificateHolderReference(DERApplicationSpecific certificateHolderReference)
209        throws IllegalArgumentException
210    {
211        if (certificateHolderReference.getApplicationTag() == EACTags.CARDHOLDER_NAME)
212        {
213            this.certificateHolderReference = certificateHolderReference;
214            certificateType |= CHR;
215        }
216        else
217        {
218            throw new IllegalArgumentException("Not an Iso7816Tags.CARDHOLDER_NAME tag");
219        }
220    }
221
222    /**
223     * set the CertificationAuthorityReference.
224     *
225     * @param certificationAuthorityReference
226     *         the DERApplicationSpecific containing the CertificationAuthorityReference.
227     * @throws IllegalArgumentException if the DERApplicationSpecific is not valid.
228     */
229    private void setCertificationAuthorityReference(
230        DERApplicationSpecific certificationAuthorityReference)
231        throws IllegalArgumentException
232    {
233        if (certificationAuthorityReference.getApplicationTag() == EACTags.ISSUER_IDENTIFICATION_NUMBER)
234        {
235            this.certificationAuthorityReference = certificationAuthorityReference;
236            certificateType |= CAR;
237        }
238        else
239        {
240            throw new IllegalArgumentException("Not an Iso7816Tags.ISSUER_IDENTIFICATION_NUMBER tag");
241        }
242    }
243
244    /**
245     * set the public Key
246     *
247     * @param publicKey : the DERApplicationSpecific containing the public key
248     * @throws java.io.IOException
249     */
250    private void setPublicKey(PublicKeyDataObject publicKey)
251    {
252        this.publicKey = PublicKeyDataObject.getInstance(publicKey);
253        this.certificateType |= PK;
254    }
255
256    /**
257     * create a request type Iso7816CertificateBody.
258     *
259     * @return return the "request" type certificate body.
260     * @throws IOException if the DERApplicationSpecific cannot be created.
261     */
262    private ASN1Primitive requestToASN1Object()
263        throws IOException
264    {
265        ASN1EncodableVector v = new ASN1EncodableVector();
266
267        v.add(certificateProfileIdentifier);
268        v.add(new DERApplicationSpecific(false, EACTags.CARDHOLDER_PUBLIC_KEY_TEMPLATE, publicKey));
269        v.add(certificateHolderReference);
270        return new DERApplicationSpecific(EACTags.CERTIFICATE_CONTENT_TEMPLATE, v);
271    }
272
273    /**
274     * create a "request" or "profile" type Iso7816CertificateBody according to the variables sets.
275     *
276     * @return return the ASN1Primitive representing the "request" or "profile" type certificate body.
277     */
278    public ASN1Primitive toASN1Primitive()
279    {
280        try
281        {
282            if (certificateType == profileType)
283            {
284                return profileToASN1Object();
285            }
286            if (certificateType == requestType)
287            {
288                return requestToASN1Object();
289            }
290        }
291        catch (IOException e)
292        {
293            return null;
294        }
295        return null;
296    }
297
298    /**
299     * gives the type of the certificate (value should be profileType or requestType if all data are set).
300     *
301     * @return the int representing the data already set.
302     */
303    public int getCertificateType()
304    {
305        return certificateType;
306    }
307
308    /**
309     * Gives an instance of Iso7816CertificateBody taken from Object obj
310     *
311     * @param obj is the Object to extract the certificate body from.
312     * @return the Iso7816CertificateBody taken from Object obj.
313     * @throws IOException if object is not valid.
314     */
315    public static CertificateBody getInstance(Object obj)
316        throws IOException
317    {
318        if (obj instanceof CertificateBody)
319        {
320            return (CertificateBody)obj;
321        }
322        else if (obj != null)
323        {
324            return new CertificateBody(DERApplicationSpecific.getInstance(obj));
325        }
326
327        return null;
328    }
329
330    /**
331     * @return the date of the certificate generation
332     */
333    public PackedDate getCertificateEffectiveDate()
334    {
335        if ((this.certificateType & CertificateBody.CEfD) ==
336            CertificateBody.CEfD)
337        {
338            return new PackedDate(certificateEffectiveDate.getContents());
339        }
340        return null;
341    }
342
343    /**
344     * set the date of the certificate generation
345     *
346     * @param ced DERApplicationSpecific containing the date of the certificate generation
347     * @throws IllegalArgumentException if the tag is not Iso7816Tags.APPLICATION_EFFECTIVE_DATE
348     */
349    private void setCertificateEffectiveDate(DERApplicationSpecific ced)
350        throws IllegalArgumentException
351    {
352        if (ced.getApplicationTag() == EACTags.APPLICATION_EFFECTIVE_DATE)
353        {
354            this.certificateEffectiveDate = ced;
355            certificateType |= CEfD;
356        }
357        else
358        {
359            throw new IllegalArgumentException("Not an Iso7816Tags.APPLICATION_EFFECTIVE_DATE tag :" + EACTags.encodeTag(ced));
360        }
361    }
362
363    /**
364     * @return the date after wich the certificate expires
365     */
366    public PackedDate getCertificateExpirationDate()
367        throws IOException
368    {
369        if ((this.certificateType & CertificateBody.CExD) ==
370            CertificateBody.CExD)
371        {
372            return new PackedDate(certificateExpirationDate.getContents());
373        }
374        throw new IOException("certificate Expiration Date not set");
375    }
376
377    /**
378     * set the date after wich the certificate expires
379     *
380     * @param ced DERApplicationSpecific containing the date after wich the certificate expires
381     * @throws IllegalArgumentException if the tag is not Iso7816Tags.APPLICATION_EXPIRATION_DATE
382     */
383    private void setCertificateExpirationDate(DERApplicationSpecific ced)
384        throws IllegalArgumentException
385    {
386        if (ced.getApplicationTag() == EACTags.APPLICATION_EXPIRATION_DATE)
387        {
388            this.certificateExpirationDate = ced;
389            certificateType |= CExD;
390        }
391        else
392        {
393            throw new IllegalArgumentException("Not an Iso7816Tags.APPLICATION_EXPIRATION_DATE tag");
394        }
395    }
396
397    /**
398     * the Iso7816CertificateHolderAuthorization encodes the role of the holder
399     * (i.e. CVCA, DV, IS) and assigns read/write access rights to data groups
400     * storing sensitive data. This functions returns the Certificate Holder
401     * Authorization
402     *
403     * @return the Iso7816CertificateHolderAuthorization
404     */
405    public CertificateHolderAuthorization getCertificateHolderAuthorization()
406        throws IOException
407    {
408        if ((this.certificateType & CertificateBody.CHA) ==
409            CertificateBody.CHA)
410        {
411            return certificateHolderAuthorization;
412        }
413        throw new IOException("Certificate Holder Authorisation not set");
414    }
415
416    /**
417     * set the CertificateHolderAuthorization
418     *
419     * @param cha the Certificate Holder Authorization
420     */
421    private void setCertificateHolderAuthorization(
422        CertificateHolderAuthorization cha)
423    {
424        this.certificateHolderAuthorization = cha;
425        certificateType |= CHA;
426    }
427
428    /**
429     * certificateHolderReference : associates the public key contained in the certificate with a unique name
430     *
431     * @return the certificateHolderReference.
432     */
433    public CertificateHolderReference getCertificateHolderReference()
434    {
435        return new CertificateHolderReference(certificateHolderReference.getContents());
436    }
437
438    /**
439     * CertificateProfileIdentifier : version of the certificate format. Must be 0 (version 1)
440     *
441     * @return the CertificateProfileIdentifier
442     */
443    public DERApplicationSpecific getCertificateProfileIdentifier()
444    {
445        return certificateProfileIdentifier;
446    }
447
448    /**
449     * get the certificationAuthorityReference
450     * certificationAuthorityReference : uniquely identifies the issuinng CA's signature key pair
451     *
452     * @return the certificationAuthorityReference
453     */
454    public CertificationAuthorityReference getCertificationAuthorityReference()
455        throws IOException
456    {
457        if ((this.certificateType & CertificateBody.CAR) ==
458            CertificateBody.CAR)
459        {
460            return new CertificationAuthorityReference(certificationAuthorityReference.getContents());
461        }
462        throw new IOException("Certification authority reference not set");
463    }
464
465    /**
466     * @return the PublicKey
467     */
468    public PublicKeyDataObject getPublicKey()
469    {
470        return publicKey;
471    }
472}