All Downloads are FREE. Search and download functionalities are using the official Maven repository.

iaik.pkcs.pkcs11.objects.Object Maven / Gradle / Ivy

There is a newer version: 1.4.10
Show newest version
// Copyright (c) 2002 Graz University of Technology. All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice,
//    this list of conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright notice,
//    this list of conditions and the following disclaimer in the documentation
//    and/or other materials provided with the distribution.
//
// 3. The end-user documentation included with the redistribution, if any, must
//    include the following acknowledgment:
//
//    "This product includes software developed by IAIK of Graz University of
//     Technology."
//
//    Alternately, this acknowledgment may appear in the software itself, if and
//    wherever such third-party acknowledgments normally appear.
//
// 4. The names "Graz University of Technology" and "IAIK of Graz University of
//    Technology" must not be used to endorse or promote products derived from
//    this software without prior written permission.
//
// 5. Products derived from this software may not be called "IAIK PKCS Wrapper",
//    nor may "IAIK" appear in their name, without prior written permission of
//    Graz University of Technology.
//
// THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED
// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE LICENSOR BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
// OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
// OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.

package iaik.pkcs.pkcs11.objects;

import java.util.Enumeration;
import java.util.Hashtable;
import java.util.Vector;

//import java.util.Collections;
import iaik.pkcs.pkcs11.Session;
import iaik.pkcs.pkcs11.TokenException;
import iaik.pkcs.pkcs11.TokenRuntimeException;
import iaik.pkcs.pkcs11.UnsupportedAttributeException;
import iaik.pkcs.pkcs11.Util;
import iaik.pkcs.pkcs11.wrapper.Constants;
import iaik.pkcs.pkcs11.wrapper.PKCS11Constants;
import iaik.pkcs.pkcs11.wrapper.PKCS11Exception;
import sun.security.pkcs11.wrapper.CK_ATTRIBUTE;
import sun.security.pkcs11.wrapper.PKCS11;

/**
 * An object of this class represents an object as defined by PKCS#11.
 * An object is of a specific class: DATA, CERTIFICATE, PUBLIC_KEY, PRIVATE_KEY,
 * SECRET_KEY, HW_FEATURE, DOMAIN_PARAMETERS or VENDOR_DEFINED.
 * If an application needs to use vendor-defined objects, it must set a
 * VendorDefinedObjectBuilder using the setVendorDefinedObjectBuilder method.
 *
 * @author Karl Scheibelhofer
 * @version 1.0
 * @invariants (attributeTable_ <> null)
 *             and (objectClass_ <> null)
 */
@SuppressWarnings("restriction")
public class Object implements Cloneable {

    /**
     * This interface defines the available object classes as defined by
     * PKCS#11:
     * DATA, CERTIFICATE, PUBLIC_KEY, PRIVATE_KEY, SECRET_KEY, HW_FEATURE,
     * DOMAIN_PARAMETERS or VENDOR_DEFINED.
     *
     * @author Karl Scheibelhofer
     * @version 1.0
     * @invariants
     */
    public interface ObjectClass {

        /**
         * The identifier for a data object or any sub-class of it.
         */
        public static final Long DATA = new Long(PKCS11Constants.CKO_DATA);

        /**
         * The identifier for a certificate object or any sub-class of it.
         */
        public static final Long CERTIFICATE
            = new Long(PKCS11Constants.CKO_CERTIFICATE);

        /**
         * The identifier for a public key object or any sub-class of it.
         */
        public static final Long PUBLIC_KEY
            = new Long(PKCS11Constants.CKO_PUBLIC_KEY);

        /**
         * The identifier for a private key object or any sub-class of it.
         */
        public static final Long PRIVATE_KEY
            = new Long(PKCS11Constants.CKO_PRIVATE_KEY);

        /**
         * The identifier for a secret key object or any sub-class of it.
         */
        public static final Long SECRET_KEY
            = new Long(PKCS11Constants.CKO_SECRET_KEY);

        /**
         * The identifier for a hardware feature object or any sub-class of it.
         */
        public static final Long HW_FEATURE
            = new Long(PKCS11Constants.CKO_HW_FEATURE);

        /**
         * The identifier for a domain parameters object or any sub-class of it.
         */
        public static final Long DOMAIN_PARAMETERS
            = new Long(PKCS11Constants.CKO_DOMAIN_PARAMETERS);

        /**
         * The identifier for a mechanism object or any sub-class of it.
         */
        public static final Long MECHANISM
            = new Long(PKCS11Constants.CKO_MECHANISM);

        /**
         * The identifier for a vendor-defined object. Any Long object with a
         * value bigger than this one is also a valid vendor-defined object
         * class identifier.
         */
        public static final Long VENDOR_DEFINED
            = new Long(PKCS11Constants.CKO_VENDOR_DEFINED);

    }

    /**
     * If an application uses vendor defined objects, it must implement this
     * interface and install such an object handler using
     * setVendorDefinedObjectBuilder.
     *
     * @author Karl Scheibelhofer
     * @version 1.0
     * @invariants
     */
    public interface VendorDefinedObjectBuilder {

        /**
         * This method should instantiate an Object of this class or of any
         * sub-class. It can use the given handles and PKCS#11 module to
         * retrieve attributes of the PKCS#11 object from the token.
         *
         * @param session
         *          The session to use for reading attributes. This session must
         *          have the appropriate rights; i.e. it must be a user-session,
         *          if it is a private object.
         * @param objectHandle
         *          The object handle as given from the PKCS#111 module.
         * @return The object representing the PKCS#11 object.
         *         The returned object can be casted to the
         *         according sub-class.
         * @exception PKCS11Exception
         *              If getting the attributes failed.
         * @preconditions (session <> null)
         * @postconditions (result <> null)
         */
        public Object build(Session session, long objectHandle)
            throws PKCS11Exception;

    }

    /**
     * The currently set vendor defined object builder, or null.
     */
    protected static VendorDefinedObjectBuilder vendorObjectBuilder_;

    /**
     * A table holding string representations for all known key types. Table key
     * is the key type as Long object.
     */
    protected static Hashtable objectClassNames_;

    /**
     * Contains all attribute objects an object possesses. No matter if an
     * attribute is set present or not, it is part of this collection.
     * The key of this table is the attribute type as Long.
     */
    protected Hashtable attributeTable_;

    /**
     * The class type of this object. One of ObjectClass, or one that has a
     * bigger value than VENDOR_DEFINED.
     */
    protected ObjectClassAttribute objectClass_;

    /**
     * The object handle as given from the PKCS#11 driver.
     */
    protected long objectHandle_ = -1;

    /**
     * The default constructor. An application use this constructor to
     * instantiate an object that serves as a template. It may also be useful
     * for working with vendor-defined objects.
     *
     * @preconditions
     * @postconditions
     */
    public Object() {
        attributeTable_ = new Hashtable<>(32);

        allocateAttributes();
    }

    /**
     * The subclasses that are used to create objects by reading the attributes
     * from the token should call this super-constructor first.
     * The getInstance method also uses this constructor, if it can not
     * determine the class type of the object or if the type class is a vendor
     * defined one.
     *
     * @param session
     *          The session to use for reading attributes. This session must
     *          have the appropriate rights; i.e. it must be a user-session, if
     *          it is a private object.
     * @param objectHandle
     *          The object handle as given from the PKCS#111 module.
     * @exception TokenException
     *              If getting the attributes failed.
     * @preconditions (session <> null)
     * @postconditions
     */
    protected Object(Session session, long objectHandle)
        throws TokenException {
        attributeTable_ = new Hashtable<>(32);

        allocateAttributes();

        objectHandle_ = objectHandle;

        readAttributes(session);
    }

    /**
     * The object creation mechanism of ObjectAccess uses this method to create
     * an instance of an PKCS#11 object. This method reads the object class
     * attribute and calls the getInstance method of the according sub-class. If
     * the object class is a vendor defined it uses the
     * VendorDefinedObjectBuilder set by the application. If no object could be
     * constructed, this method returns null.
     *
     * @param session
     *          The session to use for reading attributes. This session must
     *          have the appropriate rights; i.e. it must be a user-session, if
     *          it is a private object.
     * @param objectHandle
     *          The object handle as given from the PKCS#111 module.
     * @return The object representing the PKCS#11 object.
     *         The returned object can be casted to the
     *         according sub-class.
     * @exception TokenException
     *              If getting the attributes failed.
     * @preconditions (session <> null)
     * @postconditions (result <> null)
     */
    public static Object getInstance(Session session, long objectHandle)
        throws TokenException {
        Util.requireNonNull("session", session);

        ObjectClassAttribute objectClassAttribute = new ObjectClassAttribute();
        getAttributeValue(session, objectHandle, objectClassAttribute);

        Long objectClass = objectClassAttribute.getLongValue();

        Object newObject;

        if (objectClassAttribute.isPresent() && (objectClass != null)) {
            if (objectClass.equals(ObjectClass.PRIVATE_KEY)) {
                newObject = PrivateKey.getInstance(session, objectHandle);
            } else if (objectClass.equals(ObjectClass.PUBLIC_KEY)) {
                newObject = PublicKey.getInstance(session, objectHandle);
            } else if (objectClass.equals(ObjectClass.CERTIFICATE)) {
                newObject = Certificate.getInstance(session, objectHandle);
            } else if (objectClass.equals(ObjectClass.SECRET_KEY)) {
                newObject = SecretKey.getInstance(session, objectHandle);
            } else if (objectClass.equals(ObjectClass.DATA)) {
                newObject = Data.getInstance(session, objectHandle);
            } else if (objectClass.equals(ObjectClass.DOMAIN_PARAMETERS)) {
                newObject = DomainParameters.getInstance(session, objectHandle);
            } else if (objectClass.equals(ObjectClass.MECHANISM)) {
                newObject = Mechanism.getInstance(session, objectHandle);
            } else if (objectClass.equals(ObjectClass.HW_FEATURE)) {
                newObject = HardwareFeature.getInstance(session, objectHandle);
            } else if ((objectClass.longValue()
                            & ObjectClass.VENDOR_DEFINED.longValue()) != 0L) {
                newObject = getUnknownObject(session, objectHandle);
            } else {
                newObject = getUnknownObject(session, objectHandle);
            }
        } else {
            newObject = getUnknownObject(session, objectHandle);
        }

        return newObject;
    }

    /**
     * Try to create an object which has no or an unknown object class
     * attribute. This implementation will try to use a vendor defined object
     * builder, if such has been set. If this is impossible or fails, it will
     * create just a simple {@link iaik.pkcs.pkcs11.objects.Object Object }.
     *
     * @param session
     *          The session to use.
     * @param objectHandle
     *          The handle of the object
     * @return A new Object.
     * @throws TokenException
     *           If no object could be created.
     * @preconditions (session <> null)
     * @postconditions (result <> null)
     */
    protected static Object getUnknownObject(Session session, long objectHandle)
        throws TokenException {
        Util.requireNonNull("session", session);

        Object newObject;
        if (vendorObjectBuilder_ != null) {
            try {
                newObject = vendorObjectBuilder_.build(session, objectHandle);
            } catch (PKCS11Exception ex) {
                // we can just treat it like some unknown type of object
                newObject = new Object(session, objectHandle);
            }
        } else {
            // we can just treat it like some unknown type of object
            newObject = new Object(session, objectHandle);
        }

        return newObject;
    }

    /**
     * Set a vendor-defined object builder that should be called to create an
     * instance of an vendor-defined PKCS#11 object; i.e. an instance of a
     * vendor defined sub-class of this class.
     *
     * @param builder
     *          The vendor-defined object builder. Null to clear any previously
     *          installed vendor-defined builder.
     * @preconditions
     * @postconditions
     */
    public static void setVendorDefinedObjectBuilder(
            VendorDefinedObjectBuilder builder) {
        vendorObjectBuilder_ = builder;
    }

    /**
     * Get the given object class as string.
     *
     * @param objectClass
     *          The object class to get as string.
     * @return A string denoting the object class; e.g. "Private Key".
     * @preconditions (objectClass <> null)
     * @postconditions (result <> null)
     */
    public static String getObjectClassName(Long objectClass) {
        Util.requireNonNull("objectClass", objectClass);

        String objectClassName;
        if ((objectClass.longValue()
                & PKCS11Constants.CKO_VENDOR_DEFINED) != 0L) {
            objectClassName = "Vendor Defined";
        } else {
            if (objectClassNames_ == null) {
                // setup object class names table
                Hashtable objectClassNames = new Hashtable<>(7);
                objectClassNames.put(ObjectClass.DATA, "Data");
                objectClassNames.put(ObjectClass.CERTIFICATE, "Certificate");
                objectClassNames.put(ObjectClass.PUBLIC_KEY, "Public Key");
                objectClassNames.put(ObjectClass.PRIVATE_KEY, "Private Key");
                objectClassNames.put(ObjectClass.SECRET_KEY, "Secret Key");
                objectClassNames.put(ObjectClass.HW_FEATURE,
                        "Hardware Feature");
                objectClassNames.put(ObjectClass.DOMAIN_PARAMETERS,
                        "Domain Parameters");
                objectClassNames_ = objectClassNames;
            }

            objectClassName = (String) objectClassNames_.get(objectClass);
            if (objectClassName == null) {
                objectClassName = "";
            }
        }

        return objectClassName;
    }

    /**
     * Get the currently set vendor-defined object builder.
     *
     * @return The currently set vendor-defined object builder or null if none
     *         is set.
     * @preconditions
     * @postconditions
     */
    public static VendorDefinedObjectBuilder getVendorDefinedObjectBuilder() {
        return vendorObjectBuilder_;
    }

    /**
     * Put all attributes of the given object into the attributes table of this
     * object. This method is only static to be able to access invoke the
     * implementation of this method for each class separately (see use in
     * clone()).
     *
     * @param object
     *          The object to handle.
     * @preconditions (object <> null)
     * @postconditions
     */
    protected static void putAttributesInTable(Object object) {
        Util.requireNonNull("object", object);
        object.attributeTable_.put(Attribute.CLASS, object.objectClass_);
    }

    /**
     * Allocates the attribute objects for this class and adds them to the
     * attribute table.
     *
     * @preconditions
     * @postconditions
     */
    protected void allocateAttributes() {
        objectClass_ = new ObjectClassAttribute();

        putAttributesInTable(this);
    }

    /**
     * Create a (deep) clone of this object.
     *
     * @return A clone of this object.
     * @preconditions
     * @postconditions (result <> null)
     *                 and (result instanceof Attribute)
     *                 and (result.equals(this))
     */
    @Override
    public java.lang.Object clone() {
        Object clone;

        try {
            clone = (Object) super.clone();

            clone.objectClass_ = (ObjectClassAttribute)
                    this.objectClass_.clone();
            // a new table for the clone
            clone.attributeTable_ = new Hashtable<>(32);

            // put all cloned attributes into the new table
            putAttributesInTable(clone);
        } catch (CloneNotSupportedException ex) {
            // this must not happen, because this class is cloneable
            throw new TokenRuntimeException(
                    "An unexpected clone exception occurred.", ex);
        }

        return clone;
    }

    /**
     * Compares all member variables of this object with the other object.
     * Returns only true, if all are equal in both objects.
     *
     * @param otherObject
     *          The other object to compare to.
     * @return True, if other is an instance of this class and all member
     *         variables of both objects are equal. False, otherwise.
     * @preconditions
     * @postconditions
     */
    @Override
    public boolean equals(java.lang.Object otherObject) {
        if (this == otherObject) {
            return true;
        }

        if (!(otherObject instanceof Object)) {
            return false;
        }

        Object other = (Object) otherObject;
        return (this.objectHandle_ == other.objectHandle_)
                && this.objectClass_.equals(other.objectClass_);
    }

    /**
     * Return the table that contains all attributes of this object.
     * The key to this table is the attribute type as Long object.
     *
     * @return The table of all attributes of this object. Key is the attribute
     *         type as Long. This table is unmodifiable.
     * @preconditions
     * @postconditions (result <> null)
     */
    @SuppressWarnings("unchecked")
    public Hashtable getAttributeTable() {
        return (Hashtable) attributeTable_.clone();
    }

    /**
     * Allows for putting attributes into the table without knowing the
     * {@link Attribute} at compile-time.
     *
     * @param attribute
     *        the attribute identifier as a {@link long} value
     * @param value
     *        the value
     * @throws UnsupportedAttributeException
     *         the specified attribute identifier is not available for this
     *         {@link Object} instance.
     * @throws ClassCastException
     *         the given value type is not valid for this {@link Attribute}
     *         instance.
     */
    public void putAttribute(long attribute, java.lang.Object value)
        throws UnsupportedAttributeException {
        java.lang.Object myAttribute = getAttribute(attribute);
        if (null == myAttribute) {
            throw new UnsupportedAttributeException(
                    "Unsupported attribute 0x" + Long.toHexString(attribute)
                    + " for " + this.getClass().getName());
        }

        ((Attribute) myAttribute).setValue(value);
    }

    /**
     * Gets the attribute.
     *
     * @param attribute
     *        the attribute identifier as a {@link long} value
     * @return the attribute
     */
    public Attribute getAttribute(long attribute) {
        return (Attribute) attributeTable_.get(new Long(attribute));
    }

    /**
     * Removes the attribute.
     *
     * @param attribute
     *        the attribute identifier as a {@link long} value
     */
    public void removeAttribute(long attribute) {
        getAttribute(attribute).setPresent(false);
    }

    /**
     * Gets the object handle of the underlying PKCS#11 object on the token.
     *
     * @return The object handle of the corresponding PKCS#11 object.
     * @preconditions
     * @postconditions
     */
    public long getObjectHandle() {
        return objectHandle_;
    }

    /**
     * Sets the object handle of the underlying PKCS#11 object on the token.
     * An application will rarely need to call this method itself during normal
     * operation.
     *
     * @param objectHandle
     *          The object handle of the corresponding PKCS#11 object.
     * @preconditions
     * @postconditions
     */
    public void setObjectHandle(long objectHandle) {
        objectHandle_ = objectHandle;
    }

    /**
     * Gets the object class attribute of the PKCS#11 object. Its value must be
     * one of those defined in the ObjectClass interface or one with an value
     * bigger than ObjectClass.VENDOR_DEFINED.
     *
     * @return The object class attribute.
     * @preconditions
     * @postconditions
     */
    public LongAttribute getObjectClass() {
        return objectClass_;
    }

    /**
     * This method returns the PKCS#11 attributes of this object. The collection
     * contains CK_ATTRIBUTE objects, one for each present attribute of this
     * object; e.g. for each attribute that has a set value (which might be
     * sensitive).
     * The array representation of this collection can be used directly as input
     * for the PKCS#11 wrapper. The Session class uses this method for various
     * object operations.
     *
     * @return An collection of CK_ATTRIBUTE objects.
     * @preconditions
     * @postconditions (result <> null)
     */
    public Vector getSetAttributes() {
        Vector attributeCollection
            = new Vector<>(attributeTable_.size());

        Enumeration attributeEnumeration
            = attributeTable_.elements();
        while (attributeEnumeration.hasMoreElements()) {
            Attribute attribute = attributeEnumeration.nextElement();
            if (attribute.isPresent()) {
                CK_ATTRIBUTE ckAttribute = attribute.getCkAttribute();
                attributeCollection.addElement(ckAttribute);
            }
        }

        return attributeCollection;
    }

    /**
     * The overriding of this method should ensure that the objects of this
     * class work correctly in a hashtable.
     *
     * @return The hash code of this object.
     * @preconditions
     * @postconditions
     */
    @Override
    public int hashCode() {
        return objectClass_.hashCode() ^ ((int) objectHandle_);
    }

    /**
     * Read the values of the attributes of this object from the token.
     *
     * @param session
     *          The session to use for reading attributes. This session must
     *          have the appropriate rights; i.e. it must be a user-session, if
     *          it is a private object.
     * @exception TokenException
     *              If getting the attributes failed.
     * @preconditions (session <> null)
     * @postconditions
     */
    public void readAttributes(Session session)
        throws TokenException {
        Util.requireNonNull("session", session);
        // no attributes that we need to read, subclasses set the CLASS
        // attribute
    }

    /**
     * This method returns a string representation of the current object. The
     * output is only for debugging purposes and should not be used for other
     * purposes.
     *
     * @return A string presentation of this object for debugging output.
     * @preconditions
     * @postconditions (result <> null)
     */
    @Override
    public String toString() {
        StringBuilder buffer = new StringBuilder(32);

        buffer.append(Constants.INDENT);
        buffer.append("Object Class: ");
        if (objectClass_ != null) {
            buffer.append(objectClass_.toString());
        } else {
            buffer.append("");
        }

        return buffer.toString();
    }

    /**
     * This method returns a string representation of the current object. Some
     * parameters can be set to manipulate the output. The output is only for
     * debugging purposes and should not be used for other purposes.
     *
     * @param newline
     *        true if the output should start in a new line
     * @param withName
     *        true if the type of the attribute should be returned too
     * @param indent
     *        the indent to be used
     * @return A string presentation of this object for debugging output.
     * @preconditions
     * @postconditions (result <> null)
     */
    public String toString(boolean newline, boolean withName, String indent) {
        StringBuilder buffer = new StringBuilder(1024);

        Enumeration attributesEnumeration
            = attributeTable_.elements();
        boolean firstAttribute = !newline;
        while (attributesEnumeration.hasMoreElements()) {
            Attribute attribute = attributesEnumeration.nextElement();
            if (attribute.isPresent()) {
                if (!firstAttribute) {
                    buffer.append(Constants.NEWLINE);
                }
                buffer.append(indent);
                buffer.append(attribute.toString(withName));
                firstAttribute = false;
            }
        }

        return buffer.toString();
    }

    /**
     * This method returns the PKCS#11 attributes of an object. The array
     * contains CK_ATTRIBUTE objects, one for each set attribute of this object;
     * e.g. for each attribute that is not null.
     * The array can be used directly as input for the PKCS#11 wrapper. The
     * Session class uses this method for various object operations.
     *
     * @param object
     *          The iaik.pkcs.pkcs11.object.Object object to get the attributes
     *          from.
     * @return An array of CK_ATTRIBUTE objects. null, if the given object is
     *         null.
     * @exception PKCS11Exception
     *              If setting the attribute values.
     * @preconditions
     * @postconditions
     */
    public static CK_ATTRIBUTE[] getSetAttributes(Object object)
        throws PKCS11Exception {
        Vector setAttributes = (object != null)
                ? object.getSetAttributes() : null;
        CK_ATTRIBUTE[] ckAttributes = (setAttributes != null)
                ? Util.convertAttributesVectorToArray(setAttributes) : null;

        return ckAttributes;
    }

    /**
     * This method reads the attribute specified by attribute from
     * the token using the given session.
     * The object from which to read the attribute is specified using the
     * objectHandle. The attribute will contain
     * the results.
     * If the attempt to read the attribute returns
     * CKR_ATTRIBUTE_TYPE_INVALID, this will be indicated by
     * setting {@link Attribute#setPresent(boolean)} to false.
     * It CKR_ATTRIBUTE_SENSITIVE is returned, the attribute object is
     * marked as present
     * (by calling {@link Attribute#setPresent(boolean)} with
     * true), and in addition as sensitive by calling
     * {@link Attribute#setSensitive(boolean)} with true.
     *
     * @param session
     *          The session to use for reading the attribute.
     * @param objectHandle
     *          The handle of the object which contains the attribute.
     * @param attribute
     *          The object specifying the attribute type
     *          (see {@link Attribute#getType()}) and receiving the attribute
     *          value (see {@link Attribute#setCkAttribute(CK_ATTRIBUTE)}).
     * @exception PKCS11Exception
     *              If getting the attribute failed.
     * @preconditions (session <> null)
     *                and (attribute <> null)
     * @postconditions
     */
    protected static void getAttributeValue(Session session,
            long objectHandle,
            Attribute attribute)
        throws PKCS11Exception {
        Util.requireNonNull("session", session);

        PKCS11 pkcs11Module = session.getModule().getPKCS11Module();
        long sessionHandle = session.getSessionHandle();
        long attributeCode = attribute.getCkAttribute().type;

        try {
            CK_ATTRIBUTE[] attributeTemplateList = new CK_ATTRIBUTE[1];
            attributeTemplateList[0] = new CK_ATTRIBUTE();
            attributeTemplateList[0].type = attributeCode;
            pkcs11Module.C_GetAttributeValue(sessionHandle, objectHandle,
                    attributeTemplateList);
            attribute.setCkAttribute(attributeTemplateList[0]);
            attribute.setPresent(true);
            attribute.setSensitive(false);
        } catch (sun.security.pkcs11.wrapper.PKCS11Exception ex) {
            if (ex.getErrorCode()
                    == PKCS11Constants.CKR_ATTRIBUTE_TYPE_INVALID) {
                // this means, that some requested attributes are missing, but
                // we can ignore this and proceed; e.g. a v2.01 module won't
                // have the object ID attribute
                attribute.setPresent(false);
            } else if (ex.getErrorCode()
                    == PKCS11Constants.CKR_ATTRIBUTE_SENSITIVE) {
                // this means, that some requested attributes are missing, but
                // we can ignore this and proceed; e.g. a v2.01 module won't
                // have the object ID attribute
                attribute.setPresent(true);
                attribute.setSensitive(true);
            } else {
                // there was a different error that we should propagate
                throw new PKCS11Exception(ex);
            }
        }
    }

    /**
     * This method reads the attributes in a similar way as
     * {@link #getAttributeValue}, but a complete array at once. This can lead
     * to performance improvements. If reading all attributes at once fails, it
     * tries to read each attributes individually.
     *
     * @param session
     *          The session to use for reading the attributes.
     * @param objectHandle
     *          The handle of the object which contains the attributes.
     * @param attributes
     *          The objects specifying the attribute types
     *          (see {@link Attribute#getType()}) and receiving the attribute
     *          values (see {@link Attribute#setCkAttribute(CK_ATTRIBUTE)}).
     * @exception PKCS11Exception
     *              If getting the attributes failed.
     * @preconditions (session <> null)
     *                and (attributes <> null)
     * @postconditions
     */
    protected static void getAttributeValues(Session session,
            long objectHandle,
            Attribute[] attributes)
        throws PKCS11Exception {
        Util.requireNonNull("session", session);
        Util.requireNonNull("attributes", attributes);

        PKCS11 pkcs11Module = session.getModule().getPKCS11Module();
        long sessionHandle = session.getSessionHandle();

        try {
            CK_ATTRIBUTE[] attributeTemplateList
                = new CK_ATTRIBUTE[attributes.length];
            for (int i = 0; i < attributes.length; i++) {
                CK_ATTRIBUTE attribute = new CK_ATTRIBUTE();
                attribute.type = attributes[i].getCkAttribute().type;
                attributeTemplateList[i] = attribute;
            }
            pkcs11Module.C_GetAttributeValue(sessionHandle, objectHandle,
                        attributeTemplateList);
            for (int i = 0; i < attributes.length; i++) {
                attributes[i].setCkAttribute(attributeTemplateList[i]);
                attributes[i].setPresent(true);
                attributes[i].setSensitive(false);
            }
        } catch (sun.security.pkcs11.wrapper.PKCS11Exception ex) {
            // try to read values separately
            for (int i = 0; i < attributes.length; i++) {
                getAttributeValue(session, objectHandle, attributes[i]);
            }
        }
    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy