diff options
Diffstat (limited to 'base/tps/src/org/dogtagpki/server/tps/main/ObjectSpec.java')
-rw-r--r-- | base/tps/src/org/dogtagpki/server/tps/main/ObjectSpec.java | 456 |
1 files changed, 456 insertions, 0 deletions
diff --git a/base/tps/src/org/dogtagpki/server/tps/main/ObjectSpec.java b/base/tps/src/org/dogtagpki/server/tps/main/ObjectSpec.java new file mode 100644 index 000000000..a8dbdb1bc --- /dev/null +++ b/base/tps/src/org/dogtagpki/server/tps/main/ObjectSpec.java @@ -0,0 +1,456 @@ +package org.dogtagpki.server.tps.main; + +import java.util.ArrayList; + +import org.dogtagpki.tps.main.TPSBuffer; +import org.dogtagpki.tps.main.TPSException; + +import sun.security.pkcs11.wrapper.PKCS11Constants; + +import com.netscape.certsrv.apps.CMS; + +public class ObjectSpec { + + public ObjectSpec() + { + attributeSpecs = new ArrayList<AttributeSpec>(); + } + + final static int DATATYPE_STRING = 0; + final static int DATATYPE_INTEGER = 1; + final static int DATATYPE_BOOL_FALSE = 2; + final static int DATATYPE_BOOL_TRUE = 3; + + private long objectID; + private long fixedAttributes; + private ArrayList<AttributeSpec> attributeSpecs; + private int parseRead; + + public int getParseReadSize() { + return parseRead; + } + + /** + * Parse 'c' object. + */ + public static void parseAttributes(String objectID, ObjectSpec objectSpec, TPSBuffer b) + { + int curpos = 7; + long fixedAttrs = 0; + int xclass = 0; + int id = 0; + + /* skip first 7 bytes */ + + while (curpos < ((b.size()))) { + long attribute_id = b.getLongFrom4Bytes(curpos); + int attribute_size = b.getIntFrom2Bytes(curpos + 4); + + byte type = 0; + TPSBuffer data = new TPSBuffer(); + boolean found = false; + /* modify fixed attributes */ + + switch ((int) attribute_id) { + case (int) PKCS11Constants.CKA_TOKEN: + if (b.at(curpos + 6) != 0) { + fixedAttrs |= 0x00000080; + } + break; + case (int) PKCS11Constants.CKA_PRIVATE: + if (b.at(curpos + 6) != 0) { + fixedAttrs |= 0x00000100; + } else { + } + break; + case (int) PKCS11Constants.CKA_MODIFIABLE: + if (b.at(curpos + 6) != 0) { + fixedAttrs |= 0x00000200; + } + break; + case (int) PKCS11Constants.CKA_DERIVE: + if (b.at(curpos + 6) != 0) { + fixedAttrs |= 0x00000400; + } + break; + case (int) PKCS11Constants.CKA_LOCAL: + if (b.at(curpos + 6) != 0) { + fixedAttrs |= 0x00000800; + } + break; + case (int) PKCS11Constants.CKA_ENCRYPT: + if (b.at(curpos + 6) != 0) { + fixedAttrs |= 0x00001000; + } + break; + case (int) PKCS11Constants.CKA_DECRYPT: + if (b.at(curpos + 6) != 0) { + fixedAttrs |= 0x00002000; + } + break; + case (int) PKCS11Constants.CKA_WRAP: + if (b.at(curpos + 6) != 0) { + fixedAttrs |= 0x00004000; + } + break; + case (int) PKCS11Constants.CKA_UNWRAP: + if (b.at(curpos + 6) != 0) { + fixedAttrs |= 0x00008000; + } + break; + case (int) PKCS11Constants.CKA_SIGN: + if (b.at(curpos + 6) != 0) { + fixedAttrs |= 0x00010000; + } + break; + case (int) PKCS11Constants.CKA_SIGN_RECOVER: + if (b.at(curpos + 6) != 0) { + fixedAttrs |= 0x00020000; + } + break; + case (int) PKCS11Constants.CKA_VERIFY: + if (b.at(curpos + 6) != 0) { + fixedAttrs |= 0x00040000; + } + break; + case (int) PKCS11Constants.CKA_VERIFY_RECOVER: + if (b.at(curpos + 6) != 0) { + fixedAttrs |= 0x00080000; + } + break; + case (int) PKCS11Constants.CKA_SENSITIVE: + if (b.at(curpos + 6) != 0) { + fixedAttrs |= 0x00100000; + } + break; + case (int) PKCS11Constants.CKA_ALWAYS_SENSITIVE: + if (b.at(curpos + 6) != 0) { + fixedAttrs |= 0x00200000; + } + break; + case (int) PKCS11Constants.CKA_EXTRACTABLE: + if (b.at(curpos + 6) != 0) { + fixedAttrs |= 0x00400000; + } + break; + case (int) PKCS11Constants.CKA_NEVER_EXTRACTABLE: + if (b.at(curpos + 6) != 0) { + fixedAttrs |= 0x00800000; + } + break; + case (int) PKCS11Constants.CKA_SUBJECT: + type = DATATYPE_STRING; + data = b.substr(curpos + 6, attribute_size); + /* build by PKCS11 */ + break; + case (int) PKCS11Constants.CKA_LABEL: + type = DATATYPE_STRING; + data = b.substr(curpos + 6, attribute_size); + found = true; + break; + case (int) PKCS11Constants.CKA_MODULUS: + type = DATATYPE_STRING; + data = b.substr(curpos + 6, attribute_size); + /* build by PKCS11 */ + break; + case (int) PKCS11Constants.CKA_ID: + type = DATATYPE_STRING; + data = b.substr(curpos + 6, attribute_size); + /* build by PKCS11 */ + break; + case (int) PKCS11Constants.CKA_KEY_TYPE: + type = DATATYPE_INTEGER; + data = b.substr(curpos + 6, 4); + found = true; + /* build by PKCS11 */ + break; + case (int) PKCS11Constants.CKA_CLASS: + type = DATATYPE_INTEGER; + data = b.substr(curpos + 6, 4); + xclass = data.at(0); + /* build by PKCS11 */ + break; + case (int) PKCS11Constants.CKA_PUBLIC_EXPONENT: + type = DATATYPE_STRING; + data = b.substr(curpos + 6, attribute_size); + /* build by PKCS11 */ + break; + case (int) PKCS11Constants.CKA_CERTIFICATE_TYPE: + type = DATATYPE_INTEGER; + data = b.substr(curpos + 6, 4); + /* build by PKCS11 */ + break; + + case (int) PKCS11Constants.CKA_EC_PARAMS: + type = DATATYPE_STRING; + data = b.substr(curpos + 6, attribute_size); + found = true; + break; + + case (int) PKCS11Constants.CKA_EC_POINT: + type = DATATYPE_STRING; + data = b.substr(curpos + 6, attribute_size); + found = true; + break; + default: + CMS.debug("ObjectSpec.parseKeyBlob" + + "skipped attribute_id = " + + attribute_id); + break; + } + + if (found) { + /* add attribute spec */ + AttributeSpec attrSpec = new AttributeSpec(); + attrSpec.setAttributeID(attribute_id); + attrSpec.setType(type); + + switch (type) { + case DATATYPE_STRING: + attrSpec.setData(data); + break; + case DATATYPE_INTEGER: + attrSpec.setData(data); + break; + case DATATYPE_BOOL_FALSE: + break; + case DATATYPE_BOOL_TRUE: + break; + default: + break; + } + + objectSpec.addAttributeSpec(attrSpec); + } + + curpos += 4 + 2 + attribute_size; + } + + //Here the objectID fixed attribute gets massaged. Here's how: + // The objectID becomes the cert container id, ex: 01 + // Each key pair associated with the cert must have the same ID. + // This is done by math using the following formula: + // Given a cert id of "2", the keyAttrIds of the keys are originally + // configured as k4 and k5. Note that one is twice the cert id, and + // the other is twice the cert id plus 1. In order to map the key ids + // down to the cert's id, the code below changes both "4" and "5" back + // to "2". + + int val = (objectID.charAt(1) - '0'); + switch (objectID.charAt(0)) { + case 'c': + + id = val; + + break; + case 'k': + if ((val % 2) != 0) { + id = (val - 1) / 2; + } else { + id = (val / 2); + + } + + break; + } + + objectSpec.setFixedAttributes(fixedAttrs | (xclass << 4) | id); + } + + /** + * Parse 'c' object. + */ + public static void parseCertificateAttributes(String objectID, ObjectSpec objectSpec, TPSBuffer b) + { + parseAttributes(objectID, objectSpec, b); + } + + /** + * Parse 'k' object. + */ + public static void parseKeyAttributes(String objectID, ObjectSpec objectSpec, TPSBuffer b) + { + parseAttributes(objectID, objectSpec, b); + } + + /** + * Parse 'C' object. + */ + public static void parseCertificateBlob(String objectID, ObjectSpec objectSpec, TPSBuffer b) + { + long fixedAttrs = 0; + int xclass = 0; + int id = 0; + + AttributeSpec value = new AttributeSpec(); + value.setAttributeID((int) PKCS11Constants.CKA_VALUE); + value.setType((byte) DATATYPE_STRING); + value.setData(b); + objectSpec.addAttributeSpec(value); + + fixedAttrs = 0x00000080; /* CKA_TOKEN */ + xclass = (int) PKCS11Constants.CKO_CERTIFICATE; + id = objectID.charAt(1) - '0'; + + objectSpec.setFixedAttributes(fixedAttrs | (xclass << 4) | id); + } + + /** + * Convert object from token into object spec. + * + * Reference: + * http://netkey/design/applet_readable_object_spec-0.1.txt + * http://netkey/design/pkcs11obj.txt + * + * @throws TPSException + */ + public static ObjectSpec parseFromTokenData(long objid, TPSBuffer b) throws TPSException + { + String objectID = null; + + StringBuilder idBuilder = new StringBuilder(); + + ObjectSpec o = new ObjectSpec(); + o.setObjectID(objid); + + char[] b1 = new char[4]; + b1[0] = (char) ((objid >> 24) & 0xff); + b1[1] = (char) ((objid >> 16) & 0xff); + b1[2] = (char) ((objid >> 8) & 0xff); + b1[3] = (char) (objid & 0xff); + + idBuilder.append(b1[0]); + idBuilder.append(b1[1]); + idBuilder.append(b1[2]); + idBuilder.append(b1[3]); + + objectID = idBuilder.toString(); + switch (b1[0]) { + case 'c': /* certificate attributes */ + parseCertificateAttributes(objectID, o, b); + break; + case 'k': /* public key or private key attributes */ + parseKeyAttributes(objectID, o, b); + break; + case 'C': /* certificate in DER */ + parseCertificateBlob(objectID, o, b); + break; + default: + CMS.debug("ObjectSpec::ParseKeyBlob" + + "unknown objectID = " + objectID.charAt(0)); + throw new TPSException("ObjectSpec parseFromToken data: Invalid object type, aborting.."); + } + + return o; + } + + public static ObjectSpec parse(TPSBuffer b, int offset) throws TPSException + { + int sum = 0; + + if ((b.size() - offset) < 10) + return null; + + ObjectSpec o = new ObjectSpec(); + long id = b.getLongFrom4Bytes(offset); + + o.setObjectID(id); + long attribute = b.getLongFrom4Bytes(offset + 4); + + o.setFixedAttributes(attribute); + int count = b.getIntFrom2Bytes(offset + 8); + sum += 10; + int curpos = offset + 10; + for (int i = 0; i < count; i++) { + int len = 0; + switch (b.at(curpos + 4)) { + case DATATYPE_STRING: + len = 4 + 1 + 2 + b.getIntFrom2Bytes(curpos + 5); + break; + case DATATYPE_INTEGER: + len = 4 + 1 + 4; + break; + case DATATYPE_BOOL_FALSE: + len = 4 + 1; + break; + case DATATYPE_BOOL_TRUE: + len = 4 + 1; + break; + default: + CMS.debug("ObjectSpec::parse" + + "unknown DataType = " + b.at(curpos + 4)); + throw new TPSException("ObjectSpec parse: Invalid data type, aborting.."); + } + TPSBuffer attr = b.substr(curpos, len); + AttributeSpec attrSpec = AttributeSpec.parse(attr, 0); + o.addAttributeSpec(attrSpec); + curpos += len; + sum += len; + } + o.setParseRead(sum); + return o; + } + + private void setParseRead(int nread) { + parseRead = nread; + } + + void setObjectID(long v) + { + objectID = v; + } + + public long getObjectID() + { + return objectID; + } + + public void setFixedAttributes(long v) + { + fixedAttributes = v; + } + + public long getFixedAttributes() + { + return fixedAttributes; + } + + public int getAttributeSpecCount() + { + return attributeSpecs.size(); + } + + public AttributeSpec getAttributeSpec(int p) + { + return attributeSpecs.get(p); + } + + public void addAttributeSpec(AttributeSpec p) + { + attributeSpecs.add(p); + } + + public void removeAttributeSpec(int p) + { + attributeSpecs.remove(p); + + } + + TPSBuffer getData() + { + TPSBuffer data = new TPSBuffer(); + + data.addLong4Bytes(objectID); + data.addLong4Bytes(fixedAttributes); + + int attributeCount = getAttributeSpecCount(); + data.addInt2Bytes(attributeCount); + for (int i = 0; i < attributeCount; i++) { + AttributeSpec spec = getAttributeSpec(i); + data.add(spec.getData()); + } + + return data; + } + +} |