org.opensc.pkcs15.application.impl.ApplicationFactoryImpl.java Source code

Java tutorial

Introduction

Here is the source code for org.opensc.pkcs15.application.impl.ApplicationFactoryImpl.java

Source

/***********************************************************
 * $Id$
 * 
 * PKCS#15 cryptographic provider of the opensc project.
 * http://www.opensc-project.org
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 * Created: 26.12.2007
 * 
 ***********************************************************/

package org.opensc.pkcs15.application.impl;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import org.bouncycastle.asn1.ASN1InputStream;
import org.bouncycastle.asn1.ASN1OutputStream;
import org.opensc.pkcs15.AIDs;
import org.opensc.pkcs15.PKCS15Exception;
import org.opensc.pkcs15.application.Application;
import org.opensc.pkcs15.application.ApplicationFactory;
import org.opensc.pkcs15.asn1.ISO7816ApplicationTemplate;
import org.opensc.pkcs15.asn1.ISO7816Applications;
import org.opensc.pkcs15.token.EF;
import org.opensc.pkcs15.token.Token;
import org.opensc.pkcs15.token.TokenFileAcl;
import org.opensc.pkcs15.token.impl.EFAclImpl;
import org.opensc.pkcs15.util.Util;

/**
 * @author wglas
 *
 */
public class ApplicationFactoryImpl extends ApplicationFactory {

    public static final int DIR_PATH = 0x2F00;

    /**
     * Construct an existing application on a token.
     * 
     * Reimplement this method, if you like to add support for other application
     * IDs.
     * 
     * @param token The token on which the application has been found.
     * @param template The application template found in the DIR file.
     * @return The application object, if the AID of the template is recognized or null.
     * @throws IOException 
     */
    protected Application constructApplication(Token token, ISO7816ApplicationTemplate template)
            throws IOException {
        if (Arrays.equals(AIDs.PKCS15_AID, template.getAid()))
            return new PKCS15Application(token, template);

        return null;
    }

    /**
     * Construct a new application which will be lateron stored onto the token.
     * 
     * Reimplement this method, if you like to add support for other application
     * IDs.
     * 
     * @param token The token to which the new application will be bound.
     * @param aid The application ID.
     * @return The application object, if the application ID is recognized or null.
     * @throws IOException 
     */
    protected Application constructApplication(Token token, byte[] aid) throws IOException {
        if (Arrays.equals(AIDs.PKCS15_AID, aid))
            return new PKCS15Application(token);

        return null;
    }

    /**
     * Read the applications directory from the token
     * 
     * @param token The token to read from.
     * @return the list of ISO7816 application record in the DIR objects or
     *         null if there is no DIR record on the token.
     * @throws IOException Upon errors.
     */
    protected ISO7816Applications readApplications(Token token) throws IOException {
        token.selectMF();

        try {
            if (token.selectEF(DIR_PATH) == null)
                return null;
        } catch (PKCS15Exception e) {

            if (e.getErrorCode() == PKCS15Exception.ERROR_FILE_NOT_FOUND)
                return null;
            else
                throw e;
        }

        InputStream is = token.readEFData();

        ASN1InputStream ais = new ASN1InputStream(is);

        ISO7816Applications apps = new ISO7816Applications();

        ISO7816ApplicationTemplate template;

        while ((template = ISO7816ApplicationTemplate.getInstance(ais.readObject())) != null) {
            apps.addApplication(template);
        }

        ais.close();

        return apps;
    }

    /**
     * Write the applications directory to the token.
     * 
     * @param token The token to write to.
     * @param apps The list of application templates to write.
     * @throws IOException Upon errors.
     */
    protected void writeApplications(Token token, ISO7816Applications apps) throws IOException {
        token.selectMF();

        EF ef = null;

        try {
            ef = token.selectEF(DIR_PATH);
        } catch (PKCS15Exception e) {
            if (e.getErrorCode() != PKCS15Exception.ERROR_FILE_NOT_FOUND)
                throw e;
        }

        if (ef == null) {
            token.createEF(DIR_PATH, 512L,
                    new EFAclImpl(TokenFileAcl.AC_ALWAYS, TokenFileAcl.AC_ALWAYS, TokenFileAcl.AC_ALWAYS,
                            TokenFileAcl.AC_ALWAYS, TokenFileAcl.AC_ALWAYS, TokenFileAcl.AC_ALWAYS,
                            TokenFileAcl.AC_ALWAYS, TokenFileAcl.AC_ALWAYS, TokenFileAcl.AC_ALWAYS));

            ef = token.selectEF(DIR_PATH);
        }

        OutputStream os = token.writeEFData();

        ASN1OutputStream aos = new ASN1OutputStream(os);

        if (apps.getApplications() != null)
            for (ISO7816ApplicationTemplate template : apps.getApplications())
                aos.writeObject(template.toASN1Object());

        aos.write(0);
        aos.write(0);
        aos.close();

    }

    /* (non-Javadoc)
     * @see org.opensc.pkcs15.application.ApplicationFactory#listApplications(org.opensc.pkcs15.token.Token)
     */
    @Override
    public List<Application> listApplications(Token token) throws IOException {

        ISO7816Applications applications = this.readApplications(token);

        if (applications == null || applications.getApplications() == null)
            return null;

        List<Application> ret = new ArrayList<Application>(applications.getApplications().size());

        for (ISO7816ApplicationTemplate template : applications.getApplications()) {
            Application app = this.constructApplication(token, template);

            if (app != null)
                ret.add(app);
        }

        return ret;
    }

    /* (non-Javadoc)
     * @see org.opensc.pkcs15.application.ApplicationFactory#newApplication(org.opensc.pkcs15.token.Token, byte[])
     */
    @Override
    public Application newApplication(Token token, byte[] aid) throws IOException {

        ISO7816Applications applications = this.readApplications(token);

        if (applications == null || applications.getApplications() == null)
            return null;

        for (ISO7816ApplicationTemplate template : applications.getApplications()) {
            if (Arrays.equals(aid, template.getAid())) {
                Application app = this.constructApplication(token, template);

                if (app == null)
                    throw new IllegalArgumentException("Application with an unsupported application ID ["
                            + Util.asHex(aid) + "] has been requested from the token.");

                return app;
            }
        }

        return null;
    }

    /* (non-Javadoc)
     * @see org.opensc.pkcs15.application.ApplicationFactory#createApplication(org.opensc.pkcs15.token.Token, byte[])
     */
    @Override
    public Application createApplication(Token token, byte[] aid) throws IOException {

        Application app = this.constructApplication(token, aid);

        if (app == null)
            throw new IllegalArgumentException(
                    "An unsupported application ID [" + Util.asHex(aid) + "] has been requested for creation.");

        ISO7816Applications applications = this.readApplications(token);

        if (applications == null)
            applications = new ISO7816Applications();

        applications.addApplication(app.getApplicationTemplate());

        this.writeApplications(token, applications);

        return app;
    }
}