// 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_cert.h"

#include <base/logging.h>

#include "chaps/chaps_utility.h"

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 kCertPolicies[] = {
  {CKA_CERTIFICATE_TYPE, false, {false, false, true}, true},
  {CKA_TRUSTED, false, {true, true, true}, false},
  {CKA_CERTIFICATE_CATEGORY, false, {false, false, true}, false},
  {CKA_CHECK_VALUE, false, {false, false, true}, false},
  {CKA_START_DATE, false, {false, false, true}, false},
  {CKA_END_DATE, false, {false, false, true}, false},
  {CKA_SUBJECT, false, {false, false, true}, false},
  {CKA_VALUE, false, {false, false, true}, true},
  {CKA_URL, false, {false, false, true}, false},
  {CKA_HASH_OF_SUBJECT_PUBLIC_KEY, false, {false, false, true}, false},
  {CKA_HASH_OF_ISSUER_PUBLIC_KEY, false, {false, false, true}, false},
  {CKA_JAVA_MIDP_SECURITY_DOMAIN, false, {false, false, true}, false},
  {CKA_OWNER, false, {false, false, true}, false}
};

ObjectPolicyCert::ObjectPolicyCert() {
  AddPolicies(kCertPolicies, arraysize(kCertPolicies));
}

ObjectPolicyCert::~ObjectPolicyCert() {}

bool ObjectPolicyCert::IsObjectComplete() {
  if (!ObjectPolicyCommon::IsObjectComplete())
    return false;
  // The following logic is based on requirements for the different types of
  // certificates described in PKCS #11 v2.20: 10.6.
  CK_CERTIFICATE_TYPE type = object_->GetAttributeInt(CKA_CERTIFICATE_TYPE, 0);
  if (type == CKC_X_509_ATTR_CERT) {
    if (!object_->IsAttributePresent(CKA_OWNER)) {
      LOG(ERROR) << "Attribute is required: CKA_OWNER";
      return false;
    }
  } else {
    if (!object_->IsAttributePresent(CKA_SUBJECT)) {
      LOG(ERROR) << "Attribute is required: CKA_SUBJECT";
      return false;
    }
    bool has_url = !object_->GetAttributeString(CKA_URL).empty();
    if (!has_url && object_->GetAttributeString(CKA_VALUE).empty()) {
      LOG(ERROR) << "Both CKA_VALUE and CKA_URL are empty.";
      return false;
    }
    if (has_url &&
        (object_->GetAttributeString(CKA_HASH_OF_SUBJECT_PUBLIC_KEY).empty() ||
         object_->GetAttributeString(CKA_HASH_OF_ISSUER_PUBLIC_KEY).empty())) {
      LOG(ERROR) << "Public key hash is missing.";
      return false;
    }
  }
  return true;
}

void ObjectPolicyCert::SetDefaultAttributes() {
  ObjectPolicyCommon::SetDefaultAttributes();
  if (!object_->IsAttributePresent(CKA_CERTIFICATE_CATEGORY))
    object_->SetAttributeInt(CKA_CERTIFICATE_CATEGORY, 0);
  if (!object_->IsAttributePresent(CKA_START_DATE))
    object_->SetAttributeBool(CKA_START_DATE, "");
  if (!object_->IsAttributePresent(CKA_END_DATE))
    object_->SetAttributeBool(CKA_END_DATE, "");
  if (object_->IsAttributePresent(CKA_CERTIFICATE_TYPE)) {
    CK_CERTIFICATE_TYPE type =
        object_->GetAttributeInt(CKA_CERTIFICATE_TYPE, 0);
    if (type == CKC_X_509) {
      CK_ATTRIBUTE_TYPE empty[] = {
        CKA_ID,
        CKA_ISSUER,
        CKA_SERIAL_NUMBER,
        CKA_URL,
        CKA_HASH_OF_SUBJECT_PUBLIC_KEY,
        CKA_HASH_OF_ISSUER_PUBLIC_KEY
      };
      for (size_t i = 0; i < arraysize(empty); ++i) {
        if (!object_->IsAttributePresent(empty[i]))
          object_->SetAttributeString(empty[i], "");
      }
      if (!object_->IsAttributePresent(CKA_JAVA_MIDP_SECURITY_DOMAIN))
        object_->SetAttributeInt(CKA_JAVA_MIDP_SECURITY_DOMAIN, 0);
    } else if (type == CKC_WTLS) {
      CK_ATTRIBUTE_TYPE empty[] = {
        CKA_ISSUER,
        CKA_URL,
        CKA_HASH_OF_SUBJECT_PUBLIC_KEY,
        CKA_HASH_OF_ISSUER_PUBLIC_KEY
      };
      for (size_t i = 0; i < arraysize(empty); ++i) {
        if (!object_->IsAttributePresent(empty[i]))
          object_->SetAttributeString(empty[i], "");
      }
    } else if (type == CKC_X_509_ATTR_CERT) {
      CK_ATTRIBUTE_TYPE empty[] = {
        CKA_AC_ISSUER,
        CKA_SERIAL_NUMBER,
        CKA_ATTR_TYPES
      };
      for (size_t i = 0; i < arraysize(empty); ++i) {
        if (!object_->IsAttributePresent(empty[i]))
          object_->SetAttributeString(empty[i], "");
      }
    }
  }
}

}  // namespace chaps
