From a4682ceae6774956461edd03b2485bbacea445f4 Mon Sep 17 00:00:00 2001 From: mharmsen Date: Tue, 4 Oct 2011 01:17:41 +0000 Subject: Bugzilla Bug #688225 - (dogtagIPAv2.1) TRACKER: of the Dogtag fixes for freeIPA 2.1 git-svn-id: svn+ssh://svn.fedorahosted.org/svn/pki/tags/IPA_v2_RHEL_6_2_20111003@2252 c9f7a03b-bd48-0410-a16d-cbbf54688b0b --- pki/base/tps/src/main/ObjectSpec.cpp | 515 +++++++++++++++++++++++++++++++++++ 1 file changed, 515 insertions(+) create mode 100644 pki/base/tps/src/main/ObjectSpec.cpp (limited to 'pki/base/tps/src/main/ObjectSpec.cpp') diff --git a/pki/base/tps/src/main/ObjectSpec.cpp b/pki/base/tps/src/main/ObjectSpec.cpp new file mode 100644 index 000000000..2896a85f0 --- /dev/null +++ b/pki/base/tps/src/main/ObjectSpec.cpp @@ -0,0 +1,515 @@ +// --- BEGIN COPYRIGHT BLOCK --- +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; +// version 2.1 of the License. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, +// Boston, MA 02110-1301 USA +// +// Copyright (C) 2007 Red Hat, Inc. +// All rights reserved. +// --- END COPYRIGHT BLOCK --- + +#include +#include "prmem.h" +#include "pk11func.h" +#include "main/Buffer.h" +#include "main/ObjectSpec.h" +#include "engine/RA.h" + +#ifdef XP_WIN32 +#define TPS_PUBLIC __declspec(dllexport) +#else /* !XP_WIN32 */ +#define TPS_PUBLIC +#endif /* !XP_WIN32 */ + +ObjectSpec::ObjectSpec () +{ + for (int i = 0; i < MAX_ATTRIBUTE_SPEC; i++) { + m_attributeSpec[i] = NULL; + } + m_fixedAttributes = 0; +} + +ObjectSpec::~ObjectSpec () +{ + for (int i = 0; i < MAX_ATTRIBUTE_SPEC; i++) { + if (m_attributeSpec[i] != NULL) { + delete m_attributeSpec[i]; + m_attributeSpec[i] = NULL; + } + } +} + +#define DATATYPE_STRING 0 +#define DATATYPE_INTEGER 1 +#define DATATYPE_BOOL_FALSE 2 +#define DATATYPE_BOOL_TRUE 3 + +/** + * Parse 'c' object. + */ +void ObjectSpec::ParseAttributes(char *objectID, ObjectSpec *ObjectSpec, Buffer *b) +{ + int curpos = 7; + unsigned long fixedAttrs = 0; + unsigned int xclass = 0; + unsigned int id = 0; + + /* skip first 7 bytes */ + + while (curpos < ((int)(b->size()))) { + unsigned long attribute_id = + (((BYTE*)*b)[curpos] << 24) + + (((BYTE*)*b)[curpos+1] << 16) + + (((BYTE*)*b)[curpos+2] << 8) + + ((BYTE*)*b)[curpos+3]; + unsigned short attribute_size = + (((BYTE*)*b)[curpos+4] << 8) + + ((BYTE*)*b)[curpos+5]; + BYTE type = 0; + Buffer data; + int found = 0; + /* modify fixed attributes */ + + switch (attribute_id) { + case CKA_TOKEN: + if (((BYTE*)*b)[curpos+6]) { + fixedAttrs |= 0x00000080; + } + break; + case CKA_PRIVATE: + if (((BYTE*)*b)[curpos+6]) { + fixedAttrs |= 0x00000100; + } else { + } + break; + case CKA_MODIFIABLE: + if (((BYTE*)*b)[curpos+6]) { + fixedAttrs |= 0x00000200; + } + break; + case CKA_DERIVE: + if (((BYTE*)*b)[curpos+6]) { + fixedAttrs |= 0x00000400; + } + break; + case CKA_LOCAL: + if (((BYTE*)*b)[curpos+6]) { + fixedAttrs |= 0x00000800; + } + break; + case CKA_ENCRYPT: + if (((BYTE*)*b)[curpos+6]) { + fixedAttrs |= 0x00001000; + } + break; + case CKA_DECRYPT: + if (((BYTE*)*b)[curpos+6]) { + fixedAttrs |= 0x00002000; + } + break; + case CKA_WRAP: + if (((BYTE*)*b)[curpos+6]) { + fixedAttrs |= 0x00004000; + } + break; + case CKA_UNWRAP: + if (((BYTE*)*b)[curpos+6]) { + fixedAttrs |= 0x00008000; + } + break; + case CKA_SIGN: + if (((BYTE*)*b)[curpos+6]) { + fixedAttrs |= 0x00010000; + } + break; + case CKA_SIGN_RECOVER: + if (((BYTE*)*b)[curpos+6]) { + fixedAttrs |= 0x00020000; + } + break; + case CKA_VERIFY: + if (((BYTE*)*b)[curpos+6]) { + fixedAttrs |= 0x00040000; + } + break; + case CKA_VERIFY_RECOVER: + if (((BYTE*)*b)[curpos+6]) { + fixedAttrs |= 0x00080000; + } + break; + case CKA_SENSITIVE: + if (((BYTE*)*b)[curpos+6]) { + fixedAttrs |= 0x00100000; + } + break; + case CKA_ALWAYS_SENSITIVE: + if (((BYTE*)*b)[curpos+6]) { + fixedAttrs |= 0x00200000; + } + break; + case CKA_EXTRACTABLE: + if (((BYTE*)*b)[curpos+6]) { + fixedAttrs |= 0x00400000; + } + break; + case CKA_NEVER_EXTRACTABLE: + if (((BYTE*)*b)[curpos+6]) { + fixedAttrs |= 0x00800000; + } + break; + case CKA_SUBJECT: + type = DATATYPE_STRING; + data = b->substr(curpos+6, attribute_size); + /* build by PKCS11 */ + break; + case CKA_LABEL: + type = DATATYPE_STRING; + data = b->substr(curpos+6, attribute_size); + found = 1; + break; + case CKA_MODULUS: + type = DATATYPE_STRING; + data = b->substr(curpos+6, attribute_size); + /* build by PKCS11 */ + break; + case CKA_ID: + type = DATATYPE_STRING; + data = b->substr(curpos+6, attribute_size); + /* build by PKCS11 */ + break; + case CKA_KEY_TYPE: + type = DATATYPE_INTEGER; + data = b->substr(curpos+6, 4); + /* build by PKCS11 */ + break; + case CKA_CLASS: + type = DATATYPE_INTEGER; + data = b->substr(curpos+6, 4); + xclass = ((BYTE*)data)[0]; + /* build by PKCS11 */ + break; + case CKA_PUBLIC_EXPONENT: + type = DATATYPE_STRING; + data = b->substr(curpos+6, attribute_size); + /* build by PKCS11 */ + break; + case CKA_CERTIFICATE_TYPE: + type = DATATYPE_INTEGER; + data = b->substr(curpos+6, 4); + /* build by PKCS11 */ + break; + default: + RA::Debug("ObjectSpec::ParseKeyBlob", + "skipped attribute_id = %lx", + 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[1] - '0'); + switch (objectID[0]) { + case 'c': + id = val; +#if 0 + fixedAttrs |= + 0x00000080 /* CKA_TOKEN */ + ; +#endif + break; + case 'k': + if (val % 2) { + id = (val-1)/2; + } else { + id = (val/2); + } +#if 0 + if (xclass == CKO_PUBLIC_KEY) { + fixedAttrs |= + 0x00000800 /* CKA_LOCAL */ | + 0x00000080 /* CKA_TOKEN */ + ; + } + if (xclass == CKO_PRIVATE_KEY) { + fixedAttrs |= + 0x00000800 /* CKA_LOCAL */ | + 0x00000080 /* CKA_TOKEN */ + ; + } +#endif + break; + } + + ObjectSpec->SetFixedAttributes(fixedAttrs | (xclass << 4) | id); +} + +/** + * Parse 'c' object. + */ +void ObjectSpec::ParseCertificateAttributes(char *objectID, ObjectSpec *ObjectSpec, Buffer *b) +{ + ParseAttributes(objectID, ObjectSpec, b); +} + +/** + * Parse 'k' object. + */ +void ObjectSpec::ParseKeyAttributes(char *objectID, ObjectSpec *ObjectSpec, Buffer *b) +{ + ParseAttributes(objectID, ObjectSpec, b); +} + +/** + * Parse 'C' object. + */ +void ObjectSpec::ParseCertificateBlob(char *objectID, ObjectSpec *ObjectSpec, Buffer *b) +{ + unsigned long fixedAttrs = 0; + unsigned int xclass = 0; + unsigned int id = 0; + + AttributeSpec *value = new AttributeSpec(); + value->SetAttributeID(CKA_VALUE); + value->SetType(DATATYPE_STRING); + value->SetData(*b); + ObjectSpec->AddAttributeSpec(value); + + fixedAttrs = 0x00000080; /* CKA_TOKEN */ + xclass = CKO_CERTIFICATE; + id = objectID[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 + */ +ObjectSpec *ObjectSpec::ParseFromTokenData(unsigned long objid, Buffer *b) +{ + char objectID[4]; + + ObjectSpec *o = new ObjectSpec(); + o->SetObjectID(objid); + + objectID[0] = (char)((objid >> 24) & 0xff); + objectID[1] = (char)((objid >> 16) & 0xff); + objectID[2] = (char)((objid >> 8) & 0xff); + objectID[3] = (char)((objid) & 0xff); + + switch (objectID[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: + RA::Debug("ObjectSpec::ParseKeyBlob", + "unknown objectID = %c", objectID[0]); + /* error */ + break; + } + + return o; +} + +ObjectSpec *ObjectSpec::Parse(Buffer *b, int offset, int *nread) +{ + int sum = 0; + + + if((b->size() - offset) < 10) + return NULL; + + ObjectSpec *o = new ObjectSpec(); + unsigned long id = + (((unsigned char *)*b)[offset + 0] << 24) + + (((unsigned char *)*b)[offset + 1] << 16) + + (((unsigned char *)*b)[offset + 2] << 8) + + (((unsigned char *)*b)[offset + 3]); + + o->SetObjectID(id); + unsigned long attribute = + (((unsigned char *)*b)[offset + 4] << 24) + + (((unsigned char *)*b)[offset + 5] << 16) + + (((unsigned char *)*b)[offset + 6] << 8) + + (((unsigned char *)*b)[offset + 7]); + o->SetFixedAttributes(attribute); + unsigned short count = (((unsigned char *)*b)[offset + 8] << 8) + + ((unsigned char *)*b)[offset + 9]; + sum += 10; + int curpos = offset + 10; + for (int i = 0; i < count; i++) { + int len = 0; + switch (((unsigned char *)*b)[curpos+4]) { + case DATATYPE_STRING: + len = 4 + 1 + 2 + (((unsigned char *)*b)[curpos+5]<<8) + ((unsigned char *)*b)[curpos+6]; + 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; + } + Buffer attr = b->substr(curpos, len); + AttributeSpec *attrSpec = AttributeSpec::Parse(&attr, 0); + o->AddAttributeSpec(attrSpec); + curpos += len; + sum += len; + } + *nread = sum; + return o; +} + +void ObjectSpec::SetObjectID(unsigned long v) +{ + m_objectID = v; +} + +unsigned long ObjectSpec::GetObjectID() +{ + return m_objectID; +} + +void ObjectSpec::SetFixedAttributes(unsigned long v) +{ + m_fixedAttributes = v; +} + +unsigned long ObjectSpec::GetFixedAttributes() +{ + return m_fixedAttributes; +} + + +int ObjectSpec::GetAttributeSpecCount() +{ + for (int i = 0; i < MAX_ATTRIBUTE_SPEC; i++) { + if (m_attributeSpec[i] == NULL) { + return i; + } + } + return 0; +} + +AttributeSpec *ObjectSpec::GetAttributeSpec(int p) +{ + if (p < MAX_ATTRIBUTE_SPEC) { + if (m_attributeSpec[p] != NULL) { + return m_attributeSpec[p]; + } + } + return NULL; +} + +void ObjectSpec::AddAttributeSpec(AttributeSpec *p) +{ + for (int i = 0; i < MAX_ATTRIBUTE_SPEC; i++) { + if (m_attributeSpec[i] == NULL) { + m_attributeSpec[i] = p; + return; + } + } +} + +void ObjectSpec::RemoveAttributeSpec(int p) +{ + if (p < MAX_ATTRIBUTE_SPEC) { + if (m_attributeSpec[p] != NULL) { + delete m_attributeSpec[p]; + m_attributeSpec[p] = NULL; + } + // fill hole + int empty = p; + for (int x = p+1; x < MAX_ATTRIBUTE_SPEC; x++) { + if (m_attributeSpec[x] != NULL) { + m_attributeSpec[empty] = m_attributeSpec[x]; + m_attributeSpec[x] = NULL; + empty++; + } + } + } + +} + +Buffer ObjectSpec::GetData() +{ + Buffer data = Buffer(); + + data += Buffer(1, (BYTE)(m_objectID >> 24) & 0xff); + data += Buffer(1, (BYTE)(m_objectID >> 16) & 0xff); + data += Buffer(1, (BYTE)(m_objectID >> 8) & 0xff); + data += Buffer(1, (BYTE)(m_objectID & 0xff)); + data += Buffer(1, (BYTE)(m_fixedAttributes >> 24) & 0xff); + data += Buffer(1, (BYTE)(m_fixedAttributes >> 16) & 0xff); + data += Buffer(1, (BYTE)(m_fixedAttributes >> 8) & 0xff); + data += Buffer(1, (BYTE)(m_fixedAttributes & 0xff)); + + unsigned short attributeCount = GetAttributeSpecCount(); + data += Buffer(1, (attributeCount >> 8) & 0xff); + data += Buffer(1, attributeCount & 0xff); + for (int i = 0; i < attributeCount; i++) { + AttributeSpec *spec = GetAttributeSpec(i); + data += spec->GetData(); + } + + return data; +} -- cgit