bool P11Object::isModifiable() { // Get the CKA_MODIFIABLE attribute, when the attribute is // not present return the default value which is CK_TRUE. OSAttribute* attr = osobject->getAttribute(CKA_MODIFIABLE); return attr == NULL || attr->getBooleanValue(); }
// Get the token flags bool OSToken::getTokenFlags(CK_ULONG& flags) { if (!valid || !tokenObject->isValid()) { return false; } OSAttribute* tokenFlags = tokenObject->getAttribute(CKA_OS_TOKENFLAGS); if (tokenFlags != NULL) { flags = tokenFlags->getUnsignedLongValue(); // Check if the user PIN is initialised if (tokenObject->attributeExists(CKA_OS_USERPIN)) { flags |= CKF_USER_PIN_INITIALIZED; } return true; } else { return false; } }
bool P11Object::isCopyable() { // Get the CKA_COPYABLE attribute, when the attribute is not // present return the default value which is CK_TRUE. OSAttribute* attr = osobject->getAttribute(CKA_COPYABLE); return attr == NULL || attr->getBooleanValue(); }
bool P11Object::isPrivate() { // Get the CKA_PRIVATE attribute, when the attribute is // not present return the default value which we have // chosen to be CK_FALSE. OSAttribute* attr = osobject->getAttribute(CKA_PRIVATE); return attr != NULL && attr->getBooleanValue(); }
static bool encodeAttributeMap(ByteString& value, const std::map<CK_ATTRIBUTE_TYPE,OSAttribute>& attributes) { for (std::map<CK_ATTRIBUTE_TYPE,OSAttribute>::const_iterator i = attributes.begin(); i != attributes.end(); ++i) { CK_ATTRIBUTE_TYPE attrType = i->first; value += ByteString((unsigned char*) &attrType, sizeof(attrType)); OSAttribute attr = i->second; if (attr.isBooleanAttribute()) { AttributeKind attrKind = akBoolean; value += ByteString((unsigned char*) &attrKind, sizeof(attrKind)); bool val = attr.getBooleanValue(); value += ByteString((unsigned char*) &val, sizeof(val)); } else if (attr.isUnsignedLongAttribute()) { AttributeKind attrKind = akInteger; value += ByteString((unsigned char*) &attrKind, sizeof(attrKind)); unsigned long val = attr.getUnsignedLongValue(); value += ByteString((unsigned char*) &val, sizeof(val)); } else if (attr.isByteStringAttribute()) { AttributeKind attrKind = akBinary; value += ByteString((unsigned char*) &attrKind, sizeof(attrKind)); ByteString val = attr.getByteStringValue(); unsigned long len = val.size(); value += ByteString((unsigned char*) &len, sizeof(len)); value += val; } else if (attr.isMechanismTypeSetAttribute()) { AttributeKind attrKind = akMechSet; value += ByteString((unsigned char*) &attrKind, sizeof(attrKind)); ByteString val; encodeMechanismTypeSet(val, attr.getMechanismTypeSetValue()); unsigned long len = val.size(); value += ByteString((unsigned char*) &len, sizeof(len)); value += val; } else { ERROR_MSG("unsupported attribute kind for attribute map"); return false; } } return true; }
unsigned long DBObject::getUnsignedLongValue(CK_ATTRIBUTE_TYPE type, unsigned long val) { MutexLocker lock(_mutex); OSAttribute* attr = getAttributeDB(type); if (attr == NULL) return val; if (attr->isUnsignedLongAttribute()) { return attr->getUnsignedLongValue(); } else { ERROR_MSG("The attribute is not an unsigned long: 0x%08X", type); return val; } }
bool DBObject::getBooleanValue(CK_ATTRIBUTE_TYPE type, bool val) { MutexLocker lock(_mutex); OSAttribute* attr = getAttributeDB(type); if (attr == NULL) return val; if (attr->isBooleanAttribute()) { return attr->getBooleanValue(); } else { ERROR_MSG("The attribute is not a boolean: 0x%08X", type); return val; } }
ByteString DBObject::getByteStringValue(CK_ATTRIBUTE_TYPE type) { MutexLocker lock(_mutex); ByteString val; OSAttribute* attr = getAttributeDB(type); if (attr == NULL) return val; if (attr->isByteStringAttribute()) { return attr->getByteStringValue(); } else { ERROR_MSG("The attribute is not a byte string: 0x%08X", type); return val; } }
// Retrieve the token serial bool OSToken::getTokenSerial(ByteString& serial) { if (!valid || !tokenObject->isValid()) { return false; } OSAttribute* tokenSerial = tokenObject->getAttribute(CKA_OS_TOKENSERIAL); if (tokenSerial != NULL) { serial = tokenSerial->getByteStringValue(); return true; } else { return false; } }
// Retrieve the token label bool OSToken::getTokenLabel(ByteString& label) { if (!valid || !tokenObject->isValid()) { return false; } OSAttribute* tokenLabel = tokenObject->getAttribute(CKA_OS_TOKENLABEL); if (tokenLabel != NULL) { label = tokenLabel->getByteStringValue(); return true; } else { return false; } }
// Get the user PIN bool OSToken::getUserPIN(ByteString& userPINBlob) { if (!valid || !tokenObject->isValid()) { return false; } OSAttribute* userPIN = tokenObject->getAttribute(CKA_OS_USERPIN); if (userPIN != NULL) { userPINBlob = userPIN->getByteStringValue(); return true; } else { return false; } }
// Get the SO PIN bool OSToken::getSOPIN(ByteString& soPINBlob) { if (!valid || !tokenObject->isValid()) { return false; } OSAttribute* soPIN = tokenObject->getAttribute(CKA_OS_SOPIN); if (soPIN != NULL) { soPINBlob = soPIN->getByteStringValue(); return true; } else { return false; } }
// Set the specified attribute bool DBObject::deleteAttribute(CK_ATTRIBUTE_TYPE type) { MutexLocker lock(_mutex); if (_connection == NULL) { ERROR_MSG("Object is not connected to the database."); return false; } if (_objectId == 0) { ERROR_MSG("Cannot update invalid object."); return false; } // Retrieve and existing attribute if it exists or NULL if it doesn't OSAttribute *attr = getAttributeDB(type); if (attr == NULL) { ERROR_MSG("Cannot delete an attribute that doesn't exist."); return false; } DB::Statement statement; if (attr->isBooleanAttribute()) { // delete boolean attribute statement = _connection->prepare( "delete from attribute_boolean where type=%lu and object_id=%lld", type, _objectId); } else if (attr->isUnsignedLongAttribute()) { // delete integer attribute statement = _connection->prepare( "delete from attribute_integer where type=%lu and object_id=%lld", type, _objectId); } else if (attr->isByteStringAttribute() || attr -> isMechanismTypeSetAttribute()) { // delete binary attribute statement = _connection->prepare( "delete from attribute_binary where type=%lu and object_id=%lld", type, _objectId); } else if (attr->isAttributeMapAttribute()) { // delete attribute map attribute statement = _connection->prepare( "delete from attribute_array where type=%lu and object_id=%lld", type, _objectId); } // Statement is valid when a prepared statement has been attached to it. if (statement.isValid()) { if (!_connection->execute(statement)) { ERROR_MSG("Failed to delete attribute %lu for object %lld",type,_objectId); return false; } if (_transaction) { std::map<CK_ATTRIBUTE_TYPE,OSAttribute*>::iterator it = _transaction->find(type); if (it != _transaction->end()) { delete it->second; it->second = NULL; } } return true; } return false; }
// Set the specified attribute bool DBObject::setAttribute(CK_ATTRIBUTE_TYPE type, const OSAttribute& attribute) { MutexLocker lock(_mutex); if (_connection == NULL) { ERROR_MSG("Object is not connected to the database."); return false; } if (_objectId == 0) { ERROR_MSG("Cannot update invalid object."); return false; } // Retrieve and existing attribute if it exists or NULL if it doesn't OSAttribute *attr = getAttributeDB(type); // Update an existing attribute... if (attr) { DB::Statement statement; if (attr->isBooleanAttribute()) { // update boolean attribute statement = _connection->prepare( "update attribute_boolean set value=%d where type=%lu and object_id=%lld", attribute.getBooleanValue() ? 1 : 0, type, _objectId); } else if (attr->isUnsignedLongAttribute()) { // update integer attribute statement = _connection->prepare( "update attribute_integer set value=%lld where type=%lu and object_id=%lld", static_cast<long long>(attribute.getUnsignedLongValue()), type, _objectId); } else if (attr->isByteStringAttribute()) { // update binary attribute statement = _connection->prepare( "update attribute_binary set value=? where type=%lu and object_id=%lld", type, _objectId); DB::Bindings(statement).bindBlob(1, attribute.getByteStringValue().const_byte_str(), attribute.getByteStringValue().size(), SQLITE_STATIC); } else if (attr->isMechanismTypeSetAttribute()) { // update binary attribute ByteString value; encodeMechanismTypeSet(value, attribute.getMechanismTypeSetValue()); statement = _connection->prepare( "update attribute_binary set value=? where type=%lu and object_id=%lld", type, _objectId); DB::Bindings(statement).bindBlob(1, value.const_byte_str(), value.size(), SQLITE_TRANSIENT); } else if (attr->isAttributeMapAttribute()) { // update attribute map attribute ByteString value; if (!encodeAttributeMap(value, attribute.getAttributeMapValue())) { return false; } statement = _connection->prepare( "update attribute_array set value=? where type=%lu and object_id=%lld", type, _objectId); DB::Bindings(statement).bindBlob(1, value.const_byte_str(), value.size(), SQLITE_TRANSIENT); } // Statement is valid when a prepared statement has been attached to it. if (statement.isValid()) { if (!_connection->execute(statement)) { ERROR_MSG("Failed to update attribute %lu for object %lld",type,_objectId); return false; } if (_transaction) { std::map<CK_ATTRIBUTE_TYPE,OSAttribute*>::iterator it = _transaction->find(type); if (it != _transaction->end()) *it->second = attribute; else (*_transaction)[type] = new OSAttribute(attribute); } else *attr = attribute; return true; } } DB::Statement statement; // Insert the attribute, because it is currently unknown if (attribute.isBooleanAttribute()) { // Could not update it, so we need to insert it. statement = _connection->prepare( "insert into attribute_boolean (value,type,object_id) values (%d,%lu,%lld)", attribute.getBooleanValue() ? 1 : 0, type, _objectId); } else if (attribute.isUnsignedLongAttribute()) { // Could not update it, so we need to insert it. statement = _connection->prepare( "insert into attribute_integer (value,type,object_id) values (%lld,%lu,%lld)", static_cast<long long>(attribute.getUnsignedLongValue()), type, _objectId); } else if (attribute.isByteStringAttribute()) { // Could not update it, so we need to insert it. statement = _connection->prepare( "insert into attribute_binary (value,type,object_id) values (?,%lu,%lld)", type, _objectId); DB::Bindings(statement).bindBlob(1, attribute.getByteStringValue().const_byte_str(), attribute.getByteStringValue().size(), SQLITE_STATIC); } else if (attribute.isMechanismTypeSetAttribute()) { // Could not update it, so we need to insert it. ByteString value; encodeMechanismTypeSet(value, attribute.getMechanismTypeSetValue()); statement = _connection->prepare( "insert into attribute_binary (value,type,object_id) values (?,%lu,%lld)", type, _objectId); DB::Bindings(statement).bindBlob(1, value.const_byte_str(), value.size(), SQLITE_TRANSIENT); } else if (attribute.isAttributeMapAttribute()) { // Could not update it, so we need to insert it. ByteString value; if (!encodeAttributeMap(value, attribute.getAttributeMapValue())) { return false; } statement = _connection->prepare( "insert into attribute_array (value,type,object_id) values (?,%lu,%lld)", type, _objectId); DB::Bindings(statement).bindBlob(1, value.const_byte_str(), value.size(), SQLITE_TRANSIENT); } // Statement is valid when a prepared statement has been attached to it. if (statement.isValid()) { if (!_connection->execute(statement)) { ERROR_MSG("Failed to insert attribute %lu for object %lld",type,_objectId); return false; } if (_transaction) (*_transaction)[type] = new OSAttribute(attribute); else _attributes[type] = new OSAttribute(attribute); return true; } return false; }