blob: cb67035d613fa9e02bea8c4f36e6a9511de98ea6 [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_policy_common.h"
#include <map>
#include <base/logging.h>
#include <base/macros.h>
#include "chaps/chaps_utility.h"
#include "chaps/object.h"
using std::map;
namespace chaps {
// Read policy list as follows:
// {attribute, sensitive, read-only {create, copy, modify}, required}
// sensitive - True if attribute cannot be read.
// read-only.create - True if attribute cannot be set with C_CreateObject.
// read-only.copy - True if attribute cannot be set with C_CopyObject.
// read-only.modify - True if attribute cannot be set with C_SetAttributeValue.
// required - True if attribute is required for a valid object.
static const AttributePolicy kCommonPolicies[] = {
{CKA_CLASS, false, {false, true, true}, true},
{CKA_TOKEN, false, {false, true, true}, false},
{CKA_PRIVATE, false, {false, false, true}, false},
{CKA_MODIFIABLE, false, {false, false, true}, false},
{CKA_LABEL, false, {false, false, false}, false}
};
ObjectPolicyCommon::ObjectPolicyCommon() : object_(NULL) {
AddPolicies(kCommonPolicies, arraysize(kCommonPolicies));
}
ObjectPolicyCommon::~ObjectPolicyCommon() {}
void ObjectPolicyCommon::Init(Object* object) {
object_ = object;
}
bool ObjectPolicyCommon::IsReadAllowed(CK_ATTRIBUTE_TYPE type) {
CHECK(object_);
if (object_->GetAttributeBool(CKA_SENSITIVE, true) ||
!object_->GetAttributeBool(CKA_EXTRACTABLE, false)) {
map<CK_ATTRIBUTE_TYPE, AttributePolicy>::iterator it = policies_.find(type);
if (it != policies_.end() && it->second.is_sensitive_) {
LOG(WARNING) << "Attribute is sensitive: " << AttributeToString(type);
return false;
}
}
return true;
}
bool ObjectPolicyCommon::IsModifyAllowed(CK_ATTRIBUTE_TYPE type,
const std::string& value) {
CHECK(object_);
map<CK_ATTRIBUTE_TYPE, AttributePolicy>::iterator it = policies_.find(type);
if (it != policies_.end()) {
ObjectStage stage = object_->GetStage();
CHECK(stage < kNumObjectStages);
if (it->second.is_readonly_[stage]) {
LOG(WARNING) << "Attribute is read-only: " << AttributeToString(type);
return false;
}
}
if (type == CKA_SENSITIVE || // Read-only when true.
type == CKA_EXTRACTABLE || // Read-only when false.
type == CKA_WRAP_WITH_TRUSTED) { // Read-only when true.
bool new_value = (value[0] != 0);
bool readonly_value = (type != CKA_EXTRACTABLE);
if (readonly_value == object_->GetAttributeBool(type, !readonly_value) &&
new_value != readonly_value) {
LOG(WARNING) << "Attribute is read-only: " << AttributeToString(type);
return false;
}
}
return true;
}
bool ObjectPolicyCommon::IsObjectComplete() {
CHECK(object_);
map<CK_ATTRIBUTE_TYPE, AttributePolicy>::iterator it;
for (it = policies_.begin(); it != policies_.end(); ++it) {
if (it->second.is_required_ && !object_->IsAttributePresent(it->first)) {
LOG(ERROR) << "Attribute is required: " << AttributeToString(it->first);
return false;
}
}
return true;
}
void ObjectPolicyCommon::SetDefaultAttributes() {
CHECK(object_);
if (!object_->IsAttributePresent(CKA_TOKEN))
object_->SetAttributeBool(CKA_TOKEN, false);
if (!object_->IsAttributePresent(CKA_PRIVATE))
object_->SetAttributeBool(CKA_PRIVATE, IsPrivateClass());
if (!object_->IsAttributePresent(CKA_MODIFIABLE))
object_->SetAttributeBool(CKA_MODIFIABLE, true);
if (!object_->IsAttributePresent(CKA_LABEL))
object_->SetAttributeString(CKA_LABEL, "");
}
void ObjectPolicyCommon::AddPolicies(const AttributePolicy* policies,
int num_policies) {
for (int i = 0; i < num_policies; ++i) {
policies_[policies[i].type_] = policies[i];
}
}
bool ObjectPolicyCommon::IsPrivateClass() {
switch (object_->GetObjectClass()) {
case CKO_PUBLIC_KEY:
case CKO_CERTIFICATE:
return false;
}
return true;
}
} // namespace chaps