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

org.xipki.pkcs11.wrapper.attrs.Attribute Maven / Gradle / Ivy

There is a newer version: 1.0.9
Show newest version
// Copyright (c) 2002 Graz University of Technology. All rights reserved.
// License IAIK PKCS#11 Wrapper License.
//
// Copyright (c) 2022 xipki. All rights reserved.
// License Apache License 2.0

package org.xipki.pkcs11.wrapper.attrs;

import org.xipki.pkcs11.wrapper.AttributeVector;
import org.xipki.pkcs11.wrapper.Functions;
import org.xipki.pkcs11.wrapper.PKCS11Constants;
import sun.security.pkcs11.wrapper.CK_ATTRIBUTE;

import java.math.BigInteger;
import java.util.*;

/**
 * This is the base-class for all types of attributes. In general, all PKCS#11
 * objects are just a collection of attributes. PKCS#11 specifies which
 * attributes each type of objects must have.
 * 

* In some cases, attributes are optional. In such a case, this attribute will * return false when the application calls present() on this attribute. This * means, that the object does not possess this attribute (maybe even though * it should, but not all drivers seem to implement the standard correctly). * Handling attributes in this fashion ensures that this library can work also * with drivers that are not fully standard-compliant. *

* Moreover, certain attributes can be sensitive; i.e. their values cannot * be read, e.g. the private exponent of an RSA private key. * * @author Karl Scheibelhofer (SIC) * @author Lijun Liao (xipki) */ public abstract class Attribute { private enum AttrType { ATTRIBUTEARRAY, BOOLEAN, BYTEARRAY, CHARARRAY, DATE, LONG, MECHANISM, MECHANISMARRAY } private static final Map attributeTypes; /** * True, if the object really possesses this attribute. */ protected boolean present; /** * True, if this attribute is sensitive. */ protected boolean sensitive; /** * The CK_ATTRIBUTE that is used to hold the PKCS#11 type of this attribute * and the value. */ protected CK_ATTRIBUTE ckAttribute; static { attributeTypes = new HashMap<>(130); String propFile = "org/xipki/pkcs11/wrapper/type-CKA.properties"; Properties props = new Properties(); try { props.load(AttributeVector.class.getClassLoader().getResourceAsStream(propFile)); for (String name : props.stringPropertyNames()) { name = name.trim(); String type = props.getProperty(name).trim(); Long code = PKCS11Constants.ckaNameToCode(name); if (code == null) { throw new IllegalStateException("unknown CKA: " + name); } if (attributeTypes.containsKey(code)) { throw new IllegalStateException("duplicated definition of CKA: " + name); } AttrType attrType = AttrType.valueOf(type.toUpperCase(Locale.ROOT)); attributeTypes.put(code, attrType); } } catch (Throwable t) { throw new IllegalStateException("error reading properties file " + propFile + ": " + t.getMessage()); } if (attributeTypes.isEmpty()) { throw new IllegalStateException("no code to name map is defined properties file " + propFile); } } public abstract Object getValue(); /** * Constructor taking the PKCS#11 type of the attribute. * * @param type * The PKCS#11 type of this attribute; e.g. CKA_PRIVATE. */ protected Attribute(long type) { present = false; sensitive = false; ckAttribute = new CK_ATTRIBUTE(); ckAttribute.type = type; } public static Attribute getInstance(long type) { Attribute attr = getInstance0(type); if (attr == null) { throw new IllegalArgumentException("Unknown attribute type " + PKCS11Constants.ckaCodeToName(type)); } return attr; } static Attribute getInstance0(long type) { AttrType attrType = attributeTypes.get(type); return (attrType == AttrType.BOOLEAN) ? new BooleanAttribute(type) : (attrType == AttrType.BYTEARRAY) ? new ByteArrayAttribute(type) : (attrType == AttrType.CHARARRAY) ? new CharArrayAttribute(type) : (attrType == AttrType.DATE) ? new DateAttribute(type) : (attrType == AttrType.LONG) ? new LongAttribute(type) : (attrType == AttrType.MECHANISM) ? new MechanismAttribute(type) : (attrType == AttrType.MECHANISMARRAY) ? new MechanismArrayAttribute(type) : (attrType == AttrType.ATTRIBUTEARRAY) ? new AttributeArrayAttribute(type) : null; } public static Attribute getInstance(long type, Object value) { AttrType attrType = attributeTypes.get(type); if (attrType == AttrType.BOOLEAN) { return new BooleanAttribute(type).booleanValue((Boolean) value); } else if (attrType == AttrType.BYTEARRAY) { return (value == null || value instanceof byte[]) ? new ByteArrayAttribute(type).byteArrayValue((byte[]) value) : new ByteArrayAttribute(type).bigIntValue((BigInteger) value); } else if (attrType == AttrType.CHARARRAY) { return (value == null || value instanceof char[]) ? new CharArrayAttribute(type).charArrayValue((char[]) value) : new CharArrayAttribute(type).stringValue((String) value); } else if (attrType == AttrType.DATE) { return new DateAttribute(type).dateValue((Date) value); } else if (attrType == AttrType.LONG || attrType == AttrType.MECHANISM) { LongAttribute attr = (attrType == AttrType.LONG) ? new LongAttribute(type) : new MechanismAttribute(type); return (value == null || value instanceof Long) ? attr.longValue((Long) value) : attr.longValue((long) (int) value); } else if (attrType == AttrType.MECHANISMARRAY) { return new MechanismArrayAttribute(type).mechanismAttributeArrayValue((long[]) value); } else if (attrType == AttrType.ATTRIBUTEARRAY) { return new AttributeArrayAttribute(type).attributeArrayValue((AttributeVector) value); } else { throw new IllegalStateException("unknown attribute type " + PKCS11Constants.ckaCodeToName(type)); } } /** * Set, if this attribute is really present in the associated object. * Does only make sense if used in combination with template objects. * * @param present * True, if attribute is present. * @return a reference to this object. */ public Attribute present(boolean present) { this.present = present; return this; } /** * Set, if this attribute is sensitive in the associated object. * Does only make sense if used in combination with template objects. * * @param sensitive * True, if attribute is sensitive. * @return a reference to this object. */ public Attribute sensitive(boolean sensitive) { this.sensitive = sensitive; return this; } /** * Set the CK_ATTRIBUTE of this Attribute. Only for internal use. * * @param ckAttribute * The new CK_ATTRIBUTE of this Attribute. * @return a reference to this object. */ public Attribute ckAttribute(CK_ATTRIBUTE ckAttribute) { this.ckAttribute = Functions.requireNonNull("ckAttribute", ckAttribute); return this; } /** * Check, if this attribute is really present in the associated object. * * @return True, if this attribute is really present in the associated * object. */ public boolean isPresent() { return present; } /** * Check, if this attribute is sensitive in the associated object. * * @return True, if this attribute is sensitive in the associated object. */ public boolean isSensitive() { return sensitive; } /** * Get the CK_ATTRIBUTE object of this Attribute that contains the attribute * type and value . * * @return The CK_ATTRIBUTE of this Attribute. */ public CK_ATTRIBUTE getCkAttribute() { return ckAttribute; } public long type() { return ckAttribute.type; } /** * Get a string representation of the value of this attribute. * * @return A string representation of the value of this attribute. */ protected String getValueString() { if (ckAttribute == null || ckAttribute.pValue == null) { return ""; } long type = ckAttribute.type; Object value = ckAttribute.pValue; if (type == PKCS11Constants.CKA_CLASS) { return PKCS11Constants.ckoCodeToName((long) value); } else if (type == PKCS11Constants.CKA_KEY_TYPE) { return PKCS11Constants.ckkCodeToName((long) value); } else if (type == PKCS11Constants.CKA_CERTIFICATE_TYPE) { return PKCS11Constants.codeToName(PKCS11Constants.Category.CKC, (long) value); } else if (type == PKCS11Constants.CKA_HW_FEATURE_TYPE) { return PKCS11Constants.codeToName(PKCS11Constants.Category.CKH, (long) value); } else if (type == PKCS11Constants.CKA_CERTIFICATE_CATEGORY) { long lvalue = (long) value; return lvalue == PKCS11Constants.CK_CERTIFICATE_CATEGORY_UNSPECIFIED ? "UNSPECIFIED" : lvalue == PKCS11Constants.CK_CERTIFICATE_CATEGORY_TOKEN_USER ? "TOKEN_USER" : lvalue == PKCS11Constants.CK_CERTIFICATE_CATEGORY_AUTHORITY ? "AUTHORITY" : lvalue == PKCS11Constants.CK_CERTIFICATE_CATEGORY_OTHER_ENTITY ? "OTHER_ENTITY" : "0x" + Functions.toFullHex(lvalue); } else { return value.toString(); } } /** * Get a string representation of this attribute. If the attribute is not * present or if it is sensitive, the output of this method shows just a * message telling this. This string does not contain the attribute's type * name. * * @return A string representation of the value of this attribute. */ @Override public String toString() { return toString(true, 0, ""); } /** * Get a string representation of this attribute. If the attribute is not * present or if it is sensitive, the output of this method shows just * a message telling this. * * @param withName * If true, the string contains the attribute type name and the * value. If false, it just contains the value. * @param minNameLen Minimal length of the name. * @param indent The indent. * @return A string representation of this attribute. */ public String toString(boolean withName, int minNameLen, String indent) { StringBuilder sb = new StringBuilder(Math.max(15, minNameLen) + 20).append(indent); if (withName) { String name = PKCS11Constants.ckaCodeToName(ckAttribute.type); sb.append(name).append(": "); if (name.length() < minNameLen) { char[] padding = new char[minNameLen - name.length()]; Arrays.fill(padding, ' '); sb.append(padding); } } String valueString = present ? (sensitive ? "" : getValueString()) : ""; return sb.append(valueString).toString(); } /** * Get the PKCS#11 type of this attribute. * * @return The PKCS#11 type of this attribute. */ public long getType() { return ckAttribute.type; } public boolean isNullValue() { return ckAttribute == null || ckAttribute.pValue == null; } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy