blob: 42b6fb683e73e3c5652bb129613032f9a22c18b2 [file] [log] [blame]
// Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chaps/object_pool_impl.h"
#include <map>
#include <string>
#include <tr1/memory>
#include <vector>
#include <base/logging.h>
#include "chaps/attributes.pb.h"
#include "chaps/chaps.h"
#include "chaps/chaps_factory.h"
#include "chaps/handle_generator.h"
#include "chaps/object.h"
#include "chaps/object_store.h"
using std::map;
using std::string;
using std::tr1::shared_ptr;
using std::vector;
namespace chaps {
ObjectPoolImpl::ObjectPoolImpl(ChapsFactory* factory,
HandleGenerator* handle_generator,
ObjectStore* store)
: factory_(factory),
handle_generator_(handle_generator),
store_(store) {}
ObjectPoolImpl::~ObjectPoolImpl() {}
bool ObjectPoolImpl::Init() {
if (store_.get()) {
map<int, string> object_blobs;
if (!store_->LoadAllObjectBlobs(&object_blobs))
return false;
map<int, string>::iterator it;
for (it = object_blobs.begin(); it != object_blobs.end(); ++it) {
shared_ptr<Object> object(factory_->CreateObject());
// An object that is not parsable will be ignored.
if (Parse(it->second, object.get())) {
object->set_handle(handle_generator_->CreateHandle());
object->set_store_id(it->first);
objects_.insert(object.get());
handle_object_map_[object->handle()] = object;
} else {
LOG(WARNING) << "Object not parsable: " << it->first;
}
}
}
return true;
}
bool ObjectPoolImpl::GetInternalBlob(int blob_id, string* blob) {
if (store_.get())
return store_->GetInternalBlob(blob_id, blob);
return false;
}
bool ObjectPoolImpl::SetInternalBlob(int blob_id, const string& blob) {
if (store_.get())
return store_->SetInternalBlob(blob_id, blob);
return false;
}
bool ObjectPoolImpl::SetEncryptionKey(const string& key) {
if (store_.get())
return store_->SetEncryptionKey(key);
return true;
}
bool ObjectPoolImpl::Insert(Object* object) {
if (objects_.find(object) != objects_.end())
return false;
if (store_.get()) {
string serialized;
if (!Serialize(object, &serialized))
return false;
int store_id;
if (!store_->InsertObjectBlob(object->IsPrivate(),
object->GetObjectClass(),
object->GetAttributeString(CKA_ID),
serialized,
&store_id))
return false;
object->set_store_id(store_id);
}
object->set_handle(handle_generator_->CreateHandle());
objects_.insert(object);
handle_object_map_[object->handle()] = shared_ptr<const Object>(object);
return true;
}
bool ObjectPoolImpl::Delete(const Object* object) {
if (objects_.find(object) == objects_.end())
return false;
if (store_.get()) {
if (!store_->DeleteObjectBlob(object->store_id()))
return false;
}
handle_object_map_.erase(object->handle());
objects_.erase(object);
return true;
}
bool ObjectPoolImpl::Find(const Object* search_template,
vector<const Object*>* matching_objects) {
for (ObjectSet::iterator it = objects_.begin(); it != objects_.end(); ++it) {
if (Matches(search_template, *it))
matching_objects->push_back(*it);
}
return true;
}
bool ObjectPoolImpl::FindByHandle(int handle, const Object** object) {
CHECK(object);
HandleObjectMap::iterator it = handle_object_map_.find(handle);
if (it == handle_object_map_.end())
return false;
*object = it->second.get();
return true;
}
Object* ObjectPoolImpl::GetModifiableObject(const Object* object) {
return const_cast<Object*>(object);
}
bool ObjectPoolImpl::Flush(const Object* object) {
if (objects_.find(object) == objects_.end())
return false;
if (store_.get()) {
string serialized;
if (!Serialize(object, &serialized))
return false;
if (!store_->UpdateObjectBlob(object->store_id(), serialized))
return false;
}
return true;
}
bool ObjectPoolImpl::Matches(const Object* object_template,
const Object* object) {
const AttributeMap* attributes = object_template->GetAttributeMap();
AttributeMap::const_iterator it;
for (it = attributes->begin(); it != attributes->end(); ++it) {
if (!object->IsAttributePresent(it->first))
return false;
if (it->second != object->GetAttributeString(it->first))
return false;
}
return true;
}
bool ObjectPoolImpl::Parse(const string& object_blob, Object* object) {
AttributeList attribute_list;
if (!attribute_list.ParseFromString(object_blob)) {
LOG(ERROR) << "Failed to parse proto-buffer.";
return false;
}
for (int i = 0; i < attribute_list.attribute_size(); ++i) {
const Attribute& attribute = attribute_list.attribute(i);
if (!attribute.has_value()) {
LOG(WARNING) << "No value found for attribute: " << attribute.type();
continue;
}
object->SetAttributeString(attribute.type(), attribute.value());
}
return true;
}
bool ObjectPoolImpl::Serialize(const Object* object, string* serialized) {
const AttributeMap* attribute_map = object->GetAttributeMap();
AttributeMap::const_iterator it;
AttributeList attribute_list;
for (it = attribute_map->begin(); it != attribute_map->end(); ++it) {
Attribute* next = attribute_list.add_attribute();
next->set_type(it->first);
next->set_length(it->second.length());
next->set_value(it->second);
}
if (!attribute_list.SerializeToString(serialized)) {
LOG(ERROR) << "Failed to serialize object.";
return false;
}
return true;
}
} // namespace chaps