blob: 264a0d8f8f9b8c7d2916a0a24b024ea9d1436a6a [file] [log] [blame]
/*
* Copyright (c) 2011 .SE (The Internet Infrastructure Foundation)
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
* GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
* IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*****************************************************************************
P11Attributes.h
This file contains classes for controlling attributes
*****************************************************************************/
#include "config.h"
#include "P11Attributes.h"
#include "ByteString.h"
#include "CryptoFactory.h"
#include "DESKey.h"
#include "AESKey.h"
#include <stdio.h>
#include <stdlib.h>
// Constructor
P11Attribute::P11Attribute(OSObject* inobject)
{
osobject = inobject;
type = CKA_VENDOR_DEFINED;
size = (CK_ULONG)-1;
checks = 0;
}
// Destructor
P11Attribute::~P11Attribute()
{
}
CK_RV P11Attribute::updateAttr(Token *token, bool isPrivate, CK_VOID_PTR pValue, CK_ULONG ulValueLen, int /*op*/)
{
ByteString value;
if (isPrivate)
{
if (!token->encrypt(ByteString((unsigned char*)pValue, ulValueLen),value))
return CKR_GENERAL_ERROR;
}
else
value = ByteString((unsigned char*)pValue, ulValueLen);
if (value.size() < ulValueLen)
return CKR_GENERAL_ERROR;
osobject->setAttribute(type, value);
return CKR_OK;
}
bool P11Attribute::isModifiable()
{
// Get the CKA_MODIFIABLE attribute, when the attribute is
// not present return the default value which is CK_TRUE.
if (!osobject->attributeExists(CKA_MODIFIABLE)) return true;
return osobject->getBooleanValue(CKA_MODIFIABLE, true);
}
bool P11Attribute::isSensitive()
{
// Get the CKA_SENSITIVE attribute, when the attribute is not present
// assume the object is not sensitive.
if (!osobject->attributeExists(CKA_SENSITIVE)) return false;
return osobject->getBooleanValue(CKA_SENSITIVE, false);
}
bool P11Attribute::isExtractable()
{
// Get the CKA_EXTRACTABLE attribute, when the attribute is
// not present assume the object allows extraction.
if (!osobject->attributeExists(CKA_EXTRACTABLE)) return true;
return osobject->getBooleanValue(CKA_EXTRACTABLE, true);
}
bool P11Attribute::isTrusted()
{
// Get the CKA_TRUSTED attribute, when the attribute is
// not present assume the object is not trusted.
if (!osobject->attributeExists(CKA_TRUSTED)) return false;
return osobject->getBooleanValue(CKA_TRUSTED, false);
}
// Initialize the attribute
bool P11Attribute::init()
{
if (osobject == NULL) return false;
// Create a default value if the attribute does not exist
if (osobject->attributeExists(type) == false)
{
return setDefault();
}
return true;
}
// Return the attribute type
CK_ATTRIBUTE_TYPE P11Attribute::getType()
{
return type;
}
// Return the attribute checks
CK_ATTRIBUTE_TYPE P11Attribute::getChecks()
{
return checks;
}
// Retrieve a template map
static CK_RV retrieveAttributeMap(CK_ATTRIBUTE_PTR pTemplate, const std::map<CK_ATTRIBUTE_TYPE,OSAttribute>& map)
{
size_t nullcnt = 0;
for (size_t i = 0; i < map.size(); ++i)
{
if (pTemplate[i].pValue == NULL_PTR)
++nullcnt;
}
// Caller wants type & size
if (nullcnt == map.size())
{
std::map<CK_ATTRIBUTE_TYPE,OSAttribute>::const_iterator a = map.begin();
for (size_t i = 0; i < map.size(); ++i, ++a)
{
pTemplate[i].type = a->first;
const OSAttribute& attr = a->second;
if (attr.isBooleanAttribute())
{
pTemplate[i].ulValueLen = sizeof(CK_BBOOL);
}
else if (attr.isUnsignedLongAttribute())
{
pTemplate[i].ulValueLen = sizeof(CK_ULONG);
}
else if (attr.isByteStringAttribute())
{
pTemplate[i].ulValueLen = attr.getByteStringValue().size();
}
else
{
// Impossible
ERROR_MSG("Internal error: bad attribute in attribute map");
return CKR_GENERAL_ERROR;
}
}
return CKR_OK;
}
// Callers wants to get values
for (size_t i = 0; i < map.size(); ++i)
{
std::map<CK_ATTRIBUTE_TYPE,OSAttribute>::const_iterator a = map.find(pTemplate[i].type);
if (a == map.end())
{
pTemplate[i].ulValueLen = CK_UNAVAILABLE_INFORMATION;
return CKR_ATTRIBUTE_TYPE_INVALID;
}
const OSAttribute& attr = a->second;
if (attr.isBooleanAttribute())
{
if (pTemplate[i].ulValueLen < sizeof(CK_BBOOL))
{
pTemplate[i].ulValueLen = CK_UNAVAILABLE_INFORMATION;
return CKR_BUFFER_TOO_SMALL;
}
pTemplate[i].ulValueLen = sizeof(CK_BBOOL);
*(CK_BBOOL*)pTemplate[i].pValue = attr.getBooleanValue() ? CK_TRUE : CK_FALSE;
}
else if (attr.isUnsignedLongAttribute())
{
if (pTemplate[i].ulValueLen < sizeof(CK_ULONG))
{
pTemplate[i].ulValueLen= CK_UNAVAILABLE_INFORMATION;
return CKR_BUFFER_TOO_SMALL;
}
pTemplate[i].ulValueLen = sizeof(CK_ULONG);
*(CK_ULONG_PTR)pTemplate[i].pValue= attr.getUnsignedLongValue();
}
else if (attr.isByteStringAttribute())
{
ByteString value = attr.getByteStringValue();
if (pTemplate[i].ulValueLen < value.size())
{
pTemplate[i].ulValueLen= CK_UNAVAILABLE_INFORMATION;
return CKR_BUFFER_TOO_SMALL;
}
pTemplate[i].ulValueLen = value.size();
memcpy(pTemplate[i].pValue, value.const_byte_str(), value.size());
}
else
{
// Impossible
ERROR_MSG("Internal error: bad attribute in attribute map");
return CKR_GENERAL_ERROR;
}
}
return CKR_OK;
}
// Retrieve the value if allowed
CK_RV P11Attribute::retrieve(Token *token, bool isPrivate, CK_VOID_PTR pValue, CK_ULONG_PTR pulValueLen)
{
if (osobject == NULL) {
ERROR_MSG("Internal error: osobject field contains NULL_PTR");
return CKR_GENERAL_ERROR;
}
if (pulValueLen == NULL) {
ERROR_MSG("Internal error: pulValueLen contains NULL_PTR");
return CKR_GENERAL_ERROR;
}
// [PKCS#11 v2.40, C_GetAttributeValue]
// 1. If the specified attribute (i.e., the attribute specified by the
// type field) for the object cannot be revealed because the object
// is sensitive or unextractable, then the ulValueLen field in that
// triple is modified to hold the value CK_UNAVAILABLE_INFORMATION.
//
// [PKCS#11 v2.40, 4.2 Common attributes, table 10]
// 7 Cannot be revealed if object has its CKA_SENSITIVE attribute
// set to CK_TRUE or its CKA_EXTRACTABLE attribute set to CK_FALSE.
if ((checks & ck7) == ck7 && (isSensitive() || !isExtractable())) {
*pulValueLen = CK_UNAVAILABLE_INFORMATION;
return CKR_ATTRIBUTE_SENSITIVE;
}
// Retrieve the lower level attribute.
if (!osobject->attributeExists(type)) {
// Should be impossible.
ERROR_MSG("Internal error: attribute not present");
return CKR_GENERAL_ERROR;
}
OSAttribute attr = osobject->getAttribute(type);
// Get the actual attribute size.
CK_ULONG attrSize = size;
if (size == (CK_ULONG)-1)
{
// We don't have a fixed size attribute so we need to consult
// the lower level attribute for the exact size.
// Lower level attribute has to be variable sized.
if (attr.isByteStringAttribute())
{
if (isPrivate && attr.getByteStringValue().size() != 0)
{
ByteString value;
if (!token->decrypt(attr.getByteStringValue(),value))
{
ERROR_MSG("Internal error: failed to decrypt private attribute value");
return CKR_GENERAL_ERROR;
}
attrSize = value.size();
}
else
attrSize = attr.getByteStringValue().size();
}
else if (attr.isMechanismTypeSetAttribute())
{
attrSize = attr.getMechanismTypeSetValue().size() * sizeof(CK_MECHANISM_TYPE);
}
else if (attr.isAttributeMapAttribute())
{
attrSize = attr.getAttributeMapValue().size() * sizeof(CK_ATTRIBUTE);
}
else if (attr.isUnsignedLongAttribute())
{
attrSize = sizeof(unsigned long);
}
else
{
// Should be impossible.
ERROR_MSG("Internal error: attribute has fixed size");
return CKR_GENERAL_ERROR;
}
}
// [PKCS#11 v2.40, C_GetAttributeValue]
// 3. Otherwise, if the pValue field has the value NULL_PTR, then the
// ulValueLen field is modified to hold the exact length of the
// specified attribute for the object.
if (pValue == NULL_PTR) {
// Return the size of the attribute.
*pulValueLen = attrSize;
return CKR_OK;
}
// [PKCS#11 v2.40, C_GetAttributeValue]
// 4. Otherwise, if the length specified in ulValueLen is large enough
// to hold the value of the specified attribute for the object, then
// that attribute is copied into the buffer located at pValue, and
// the ulValueLen field is modified to hold the exact length of the
// attribute.
if (*pulValueLen >= attrSize)
{
// Only copy when there is actually something to copy
CK_RV rv = CKR_OK;
if (attr.isUnsignedLongAttribute()) {
*(CK_ULONG_PTR)pValue = attr.getUnsignedLongValue();
}
else if (attr.isBooleanAttribute())
{
*(CK_BBOOL*)pValue = attr.getBooleanValue() ? CK_TRUE : CK_FALSE;
}
else if (attr.isByteStringAttribute())
{
if (isPrivate && attr.getByteStringValue().size() != 0)
{
ByteString value;
if (!token->decrypt(attr.getByteStringValue(),value))
{
ERROR_MSG("Internal error: failed to decrypt private attribute value");
return CKR_GENERAL_ERROR;
}
const unsigned char* attrPtr = value.const_byte_str();
memcpy(pValue,attrPtr,attrSize);
}
else if (attr.getByteStringValue().size() != 0)
{
const unsigned char* attrPtr = attr.getByteStringValue().const_byte_str();
memcpy(pValue,attrPtr,attrSize);
}
}
else if (attr.isMechanismTypeSetAttribute())
{
CK_MECHANISM_TYPE_PTR pTemplate = (CK_MECHANISM_TYPE_PTR) pValue;
size_t i = 0;
std::set<CK_MECHANISM_TYPE> set = attr.getMechanismTypeSetValue();
for (std::set<CK_MECHANISM_TYPE>::const_iterator it = set.begin(); it != set.end(); ++it)
pTemplate[++i] = *it;
}
else
{
// attr is already retrieved and verified to be an Attribute Map
rv = retrieveAttributeMap((CK_ATTRIBUTE_PTR)pValue, attr.getAttributeMapValue());
}
*pulValueLen = attrSize;
return rv;
}
// [PKCS#11 v2.40, C_GetAttributeValue]
// 5. Otherwise, the ulValueLen field is modified to hold the value CK_UNAVAILABLE_INFORMATION.
*pulValueLen = CK_UNAVAILABLE_INFORMATION;
return CKR_BUFFER_TOO_SMALL;
}
// Update the value if allowed
CK_RV P11Attribute::update(Token* token, bool isPrivate, CK_VOID_PTR pValue, CK_ULONG ulValueLen, int op)
{
if (osobject == NULL) {
ERROR_MSG("Internal error: osobject field contains NULL_PTR");
return CKR_GENERAL_ERROR;
}
// [PKCS#11 v2.40, 4.1.1 Creating objects]
// 2. If the supplied template specifies an invalid value for a valid attribute, then the
// attempt should fail with the error code CKR_ATTRIBUTE_VALUE_INVALID.
// The valid values for Cryptoki attributes are described in the Cryptoki specification.
// Check for null pointers in values.
if (pValue == NULL_PTR && ulValueLen != 0) {
ERROR_MSG("The attribute is a NULL_PTR but has a non-zero length")
return CKR_ATTRIBUTE_VALUE_INVALID;
}
// For fixed sized attributes check that the size matches.
if (size != ((CK_ULONG)-1) && size != ulValueLen) {
ERROR_MSG("The attribute size is different from the expected size")
return CKR_ATTRIBUTE_VALUE_INVALID;
}
// [PKCS#11 v2.40, 4.1.1 Creating objects] OBJECT_OP_CREATE | OBJECT_OP_SET | OBJECT_OP_COPY
// 3. If the supplied template specifies a value for a read-only attribute, then the attempt
// should fail with the error code CKR_ATTRIBUTE_READ_ONLY.
// Whether or not a given Cryptoki attribute is read-only is explicitly stated in the Cryptoki
// specification; however, a particular library and token may be even more restrictive than
// Cryptoki specifies. In other words, an attribute which Cryptoki says is not read-only may
// nonetheless be read-only under certain circumstances (i.e., in conjunction with some
// combinations of other attributes) for a particular library and token. Whether or not a
// given non-Cryptoki attribute is read-only is obviously outside the scope of Cryptoki.
// Attributes cannot be changed if CKA_MODIFIABLE is set to false
if (!isModifiable() && op != OBJECT_OP_GENERATE && op != OBJECT_OP_CREATE) {
ERROR_MSG("An object is with CKA_MODIFIABLE set to false is not modifiable");
return CKR_ATTRIBUTE_READ_ONLY;
}
// Attributes cannot be modified if CKA_TRUSTED is true on a certificate object.
if (isTrusted() && op != OBJECT_OP_GENERATE && op != OBJECT_OP_CREATE) {
if (osobject->getUnsignedLongValue(CKA_CLASS, CKO_VENDOR_DEFINED) == CKO_CERTIFICATE)
{
ERROR_MSG("A trusted certificate cannot be modified");
return CKR_ATTRIBUTE_READ_ONLY;
}
}
// ck2 MUST not be specified when object is created with C_CreateObject.
if ((checks & ck2) == ck2)
{
if (OBJECT_OP_CREATE==op)
{
ERROR_MSG("Prohibited attribute was passed to object creation function");
return CKR_ATTRIBUTE_READ_ONLY;
}
}
// ck4 MUST not be specified when object is generated with C_GenerateKey or C_GenerateKeyPair.
if ((checks & ck4) == ck4)
{
if (OBJECT_OP_GENERATE==op)
{
ERROR_MSG("Prohibited attribute was passed to key generation function");
return CKR_ATTRIBUTE_READ_ONLY;
}
}
// ck6 MUST not be specified when object is unwrapped with C_UnwrapKey.
if ((checks & ck6) == ck6)
{
if (OBJECT_OP_UNWRAP==op)
{
ERROR_MSG("Prohibited attribute was passed to key unwrapping function");
return CKR_ATTRIBUTE_READ_ONLY;
}
}
// ck8 May be modified after object is created with a C_SetAttributeValue call
// or in the process of copying an object with a C_CopyObject call.
// However, it is possible that a particular token may not permit modification of
// the attribute during the course of a C_CopyObject call.
if ((checks & ck8) == ck8)
{
if (OBJECT_OP_SET==op || OBJECT_OP_COPY==op)
{
return updateAttr(token, isPrivate, pValue, ulValueLen, op);
}
}
// ck17 Can be changed in the process of copying the object using C_CopyObject.
if ((checks & ck17) == ck17)
{
if (OBJECT_OP_COPY==op)
{
return updateAttr(token, isPrivate, pValue, ulValueLen, op);
}
}
// For attributes that have not been explicitly excluded from modification
// during create/derive/generate/unwrap, we allow them to be modified.
if (OBJECT_OP_CREATE==op || OBJECT_OP_DERIVE==op || OBJECT_OP_GENERATE==op || OBJECT_OP_UNWRAP==op)
{
return updateAttr(token, isPrivate, pValue, ulValueLen, op);
}
return CKR_ATTRIBUTE_READ_ONLY;
}
/*****************************************
* CKA_CLASS
*****************************************/
// Set default value
bool P11AttrClass::setDefault()
{
OSAttribute attrClass((unsigned long)CKO_VENDOR_DEFINED);
return osobject->setAttribute(type, attrClass);
}
// Update the value if allowed
CK_RV P11AttrClass::updateAttr(Token* /*token*/, bool /*isPrivate*/, CK_VOID_PTR pValue, CK_ULONG ulValueLen, int /*op*/)
{
// Attribute specific checks
if (ulValueLen !=sizeof(CK_ULONG))
{
return CKR_ATTRIBUTE_VALUE_INVALID;
}
if (osobject->getUnsignedLongValue(CKA_CLASS, CKO_VENDOR_DEFINED) != *(CK_ULONG*)pValue)
{
return CKR_TEMPLATE_INCONSISTENT;
}
return CKR_OK;
}
/*****************************************
* CKA_KEY_TYPE
*****************************************/
// Set default value
bool P11AttrKeyType::setDefault()
{
OSAttribute attr((unsigned long)CKK_VENDOR_DEFINED);
return osobject->setAttribute(type, attr);
}
// Update the value if allowed
CK_RV P11AttrKeyType::updateAttr(Token* /*token*/, bool /*isPrivate*/, CK_VOID_PTR pValue, CK_ULONG ulValueLen, int /*op*/)
{
// Attribute specific checks
if (ulValueLen !=sizeof(CK_ULONG))
{
return CKR_ATTRIBUTE_VALUE_INVALID;
}
if (osobject->getUnsignedLongValue(CKA_KEY_TYPE, CKK_VENDOR_DEFINED) != *(CK_ULONG*)pValue)
{
return CKR_TEMPLATE_INCONSISTENT;
}
return CKR_OK;
}
/*****************************************
* CKA_CERTIFICATE_TYPE
* footnote 1
* 1 MUST be specified when object is created with C_CreateObject.
*****************************************/
// Set default value
bool P11AttrCertificateType::setDefault()
{
OSAttribute attr((unsigned long)CKC_VENDOR_DEFINED);
return osobject->setAttribute(type, attr);
}
// Update the value if allowed
CK_RV P11AttrCertificateType::updateAttr(Token* /*token*/, bool /*isPrivate*/, CK_VOID_PTR pValue, CK_ULONG ulValueLen, int /*op*/)
{
// Attribute specific checks
if (ulValueLen !=sizeof(CK_ULONG))
{
return CKR_ATTRIBUTE_VALUE_INVALID;
}
if (osobject->getUnsignedLongValue(CKA_CERTIFICATE_TYPE, CKC_VENDOR_DEFINED) != *(CK_ULONG*)pValue)
{
return CKR_TEMPLATE_INCONSISTENT;
}
return CKR_OK;
}
/*****************************************
* CKA_TOKEN
*****************************************/
// Set default value
bool P11AttrToken::setDefault()
{
OSAttribute attr(false);
return osobject->setAttribute(type, attr);
}
// Update the value if allowed
CK_RV P11AttrToken::updateAttr(Token* /*token*/, bool /*isPrivate*/, CK_VOID_PTR pValue, CK_ULONG ulValueLen, int /*op*/)
{
OSAttribute attrTrue(true);
OSAttribute attrFalse(false);
// Attribute specific checks
if (ulValueLen !=sizeof(CK_BBOOL))
{
return CKR_ATTRIBUTE_VALUE_INVALID;
}
// Store data
if (*(CK_BBOOL*)pValue == CK_FALSE)
{
osobject->setAttribute(type, attrFalse);
}
else
{
osobject->setAttribute(type, attrTrue);
}
return CKR_OK;
}
/*****************************************
* CKA_PRIVATE
*****************************************/
// Set default value
bool P11AttrPrivate::setDefault()
{
OSAttribute attr(true);
return osobject->setAttribute(type, attr);
}
// Update the value if allowed
CK_RV P11AttrPrivate::updateAttr(Token* /*token*/, bool /*isPrivate*/, CK_VOID_PTR pValue, CK_ULONG ulValueLen, int /*op*/)
{
OSAttribute attrTrue(true);
OSAttribute attrFalse(false);
// Attribute specific checks
if (ulValueLen !=sizeof(CK_BBOOL))
{
return CKR_ATTRIBUTE_VALUE_INVALID;
}
// Store data
if (*(CK_BBOOL*)pValue == CK_FALSE)
{
osobject->setAttribute(type, attrFalse);
}
else
{
osobject->setAttribute(type, attrTrue);
}
return CKR_OK;
}
/*****************************************
* CKA_MODIFIABLE
*****************************************/
// Set default value
bool P11AttrModifiable::setDefault()
{
OSAttribute attr(true);
return osobject->setAttribute(type, attr);
}
// Update the value if allowed
CK_RV P11AttrModifiable::updateAttr(Token* /*token*/, bool /*isPrivate*/, CK_VOID_PTR pValue, CK_ULONG ulValueLen, int /*op*/)
{
OSAttribute attrTrue(true);
OSAttribute attrFalse(false);
// Attribute specific checks
if (ulValueLen !=sizeof(CK_BBOOL))
{
return CKR_ATTRIBUTE_VALUE_INVALID;
}
// Store data
if (*(CK_BBOOL*)pValue == CK_FALSE)
{
osobject->setAttribute(type, attrFalse);
}
else
{
osobject->setAttribute(type, attrTrue);
}
return CKR_OK;
}
/*****************************************
* CKA_LABEL
*****************************************/
// Set default value
bool P11AttrLabel::setDefault()
{
OSAttribute attr(ByteString(""));
return osobject->setAttribute(type, attr);
}
/*****************************************
* CKA_COPYABLE
*****************************************/
// Set default value
bool P11AttrCopyable::setDefault()
{
OSAttribute attr(true);
return osobject->setAttribute(type, attr);
}
// Update the value if allowed
CK_RV P11AttrCopyable::updateAttr(Token* /*token*/, bool /*isPrivate*/, CK_VOID_PTR pValue, CK_ULONG ulValueLen, int /*op*/)
{
OSAttribute attrTrue(true);
OSAttribute attrFalse(false);
// Attribute specific checks
if (ulValueLen !=sizeof(CK_BBOOL))
{
return CKR_ATTRIBUTE_VALUE_INVALID;
}
// Store data
if (*(CK_BBOOL*)pValue == CK_FALSE)
{
osobject->setAttribute(type, attrFalse);
}
else
{
if (osobject->getBooleanValue(CKA_COPYABLE, true) == false)
{
return CKR_ATTRIBUTE_READ_ONLY;
}
}
return CKR_OK;
}
/*****************************************
* CKA_DESTROYABLE
*****************************************/
// Set default value
bool P11AttrDestroyable::setDefault()
{
OSAttribute attr(true);
return osobject->setAttribute(type, attr);
}
// Update the value if allowed
CK_RV P11AttrDestroyable::updateAttr(Token* /*token*/, bool /*isPrivate*/, CK_VOID_PTR pValue, CK_ULONG ulValueLen, int /*op*/)
{
OSAttribute attrTrue(true);
OSAttribute attrFalse(false);
// Attribute specific checks
if (ulValueLen !=sizeof(CK_BBOOL))
{
return CKR_ATTRIBUTE_VALUE_INVALID;
}
// Store data
if (*(CK_BBOOL*)pValue == CK_FALSE)
{
osobject->setAttribute(type, attrFalse);
}
else
{
osobject->setAttribute(type, attrTrue);
}
return CKR_OK;
}
/*****************************************
* CKA_APPLICATION
*****************************************/
// Set default value
bool P11AttrApplication::setDefault()
{
OSAttribute attr(ByteString(""));
return osobject->setAttribute(type, attr);
}
/*****************************************
* CKA_OBJECT_ID
*****************************************/
// Set default value
bool P11AttrObjectID::setDefault()
{
OSAttribute attr(ByteString(""));
return osobject->setAttribute(type, attr);
}
/*****************************************
* CKA_CHECK_VALUE
*****************************************/
// Set default value
bool P11AttrCheckValue::setDefault()
{
OSAttribute attr(ByteString(""));
return osobject->setAttribute(type, attr);
}
// Update the value if allowed
CK_RV P11AttrCheckValue::updateAttr(Token *token, bool isPrivate, CK_VOID_PTR pValue, CK_ULONG ulValueLen, int /*op*/)
{
ByteString plaintext((unsigned char*)pValue, ulValueLen);
ByteString value;
// Encrypt
if (isPrivate)
{
if (!token->encrypt(plaintext, value))
return CKR_GENERAL_ERROR;
}
else
value = plaintext;
// Attribute specific checks
if (value.size() < ulValueLen)
return CKR_GENERAL_ERROR;
// Store data
if (ulValueLen == 0)
{
osobject->setAttribute(type, value);
}
else
{
ByteString checkValue;
ByteString keybits;
if (isPrivate)
{
if (!token->decrypt(osobject->getByteStringValue(CKA_VALUE), keybits))
return CKR_GENERAL_ERROR;
}
else
{
keybits = osobject->getByteStringValue(CKA_VALUE);
}
SymmetricKey key;
AESKey aes;
DESKey des;
switch (osobject->getUnsignedLongValue(CKA_KEY_TYPE, CKK_VENDOR_DEFINED))
{
case CKK_GENERIC_SECRET:
case CKK_MD5_HMAC:
case CKK_SHA_1_HMAC:
case CKK_SHA224_HMAC:
case CKK_SHA256_HMAC:
case CKK_SHA384_HMAC:
case CKK_SHA512_HMAC:
key.setKeyBits(keybits);
key.setBitLen(keybits.size() * 8);
checkValue = key.getKeyCheckValue();
break;
case CKK_AES:
aes.setKeyBits(keybits);
aes.setBitLen(keybits.size() * 8);
checkValue = aes.getKeyCheckValue();
break;
case CKK_DES:
case CKK_DES2:
case CKK_DES3:
des.setKeyBits(keybits);
des.setBitLen(keybits.size() * 7);
checkValue = des.getKeyCheckValue();
break;
case CKK_GOST28147:
// TODO: Encryption support for CKK_GOST28147
// We do not calculate the KCV
checkValue = plaintext;
break;
default:
return CKR_GENERAL_ERROR;
}
if (plaintext != checkValue)
return CKR_ATTRIBUTE_VALUE_INVALID;
osobject->setAttribute(type, value);
}
return CKR_OK;
}
/*****************************************
* CKA_PUBLIC_KEY_INFO
*****************************************/
// Set default value
bool P11AttrPublicKeyInfo::setDefault()
{
OSAttribute attr(ByteString(""));
return osobject->setAttribute(type, attr);
}
/*****************************************
* CKA_ID
*****************************************/
// Set default value
bool P11AttrID::setDefault()
{
OSAttribute attr(ByteString(""));
return osobject->setAttribute(type, attr);
}
/*****************************************
* CKA_VALUE
*****************************************/
// Set default value
bool P11AttrValue::setDefault()
{
OSAttribute attr(ByteString(""));
return osobject->setAttribute(type, attr);
}
// Update the value if allowed
CK_RV P11AttrValue::updateAttr(Token *token, bool isPrivate, CK_VOID_PTR pValue, CK_ULONG ulValueLen, int op)
{
ByteString plaintext((unsigned char*)pValue, ulValueLen);
ByteString value;
// Encrypt
if (isPrivate)
{
if (!token->encrypt(plaintext, value))
return CKR_GENERAL_ERROR;
}
else
value = plaintext;
// Attribute specific checks
if (value.size() < ulValueLen)
return CKR_GENERAL_ERROR;
// Store data
osobject->setAttribute(type, value);
// Set the size during C_CreateObject and C_UnwrapKey.
if (op == OBJECT_OP_CREATE || op == OBJECT_OP_UNWRAP)
{
// Set the CKA_VALUE_LEN
if (osobject->attributeExists(CKA_VALUE_LEN))
{
OSAttribute bytes((unsigned long)plaintext.size());
osobject->setAttribute(CKA_VALUE_LEN, bytes);
}
// Set the CKA_VALUE_BITS
if (osobject->attributeExists(CKA_VALUE_BITS))
{
OSAttribute bits((unsigned long)plaintext.bits());
osobject->setAttribute(CKA_VALUE_BITS, bits);
}
}
// Calculate the CKA_CHECK_VALUE for certificates
if (osobject->getUnsignedLongValue(CKA_CLASS, CKO_VENDOR_DEFINED) == CKO_CERTIFICATE)
{
HashAlgorithm* hash = CryptoFactory::i()->getHashAlgorithm(HashAlgo::SHA1);
if (hash == NULL) return CKR_GENERAL_ERROR;
ByteString digest;
if (hash->hashInit() == false ||
hash->hashUpdate(plaintext) == false ||
hash->hashFinal(digest) == false)
{
CryptoFactory::i()->recycleHashAlgorithm(hash);
return CKR_GENERAL_ERROR;
}
CryptoFactory::i()->recycleHashAlgorithm(hash);
// First three bytes of the SHA-1 hash
digest.resize(3);
if (isPrivate)
{
ByteString encrypted;
if (!token->encrypt(digest, encrypted))
return CKR_GENERAL_ERROR;
osobject->setAttribute(CKA_CHECK_VALUE, encrypted);
}
else
osobject->setAttribute(CKA_CHECK_VALUE, digest);
}
// Calculate the CKA_CHECK_VALUE for secret keys
if (op == OBJECT_OP_CREATE &&
osobject->getUnsignedLongValue(CKA_CLASS, CKO_VENDOR_DEFINED) == CKO_SECRET_KEY)
{
SymmetricKey key;
AESKey aes;
DESKey des;
ByteString checkValue;
switch (osobject->getUnsignedLongValue(CKA_KEY_TYPE, CKK_VENDOR_DEFINED))
{
case CKK_GENERIC_SECRET:
case CKK_MD5_HMAC:
case CKK_SHA_1_HMAC:
case CKK_SHA224_HMAC:
case CKK_SHA256_HMAC:
case CKK_SHA384_HMAC:
case CKK_SHA512_HMAC:
key.setKeyBits(plaintext);
key.setBitLen(plaintext.size() * 8);
checkValue = key.getKeyCheckValue();
break;
case CKK_AES:
aes.setKeyBits(plaintext);
aes.setBitLen(plaintext.size() * 8);
checkValue = aes.getKeyCheckValue();
break;
case CKK_DES:
case CKK_DES2:
case CKK_DES3:
des.setKeyBits(plaintext);
des.setBitLen(plaintext.size() * 7);
checkValue = des.getKeyCheckValue();
break;
case CKK_GOST28147:
// TODO: Encryption support for CKK_GOST28147
// We do not calculate the KCV
break;
default:
return CKR_GENERAL_ERROR;
}
if (isPrivate)
{
ByteString encrypted;
if (!token->encrypt(checkValue, encrypted))
return CKR_GENERAL_ERROR;
osobject->setAttribute(CKA_CHECK_VALUE, encrypted);
}
else
osobject->setAttribute(CKA_CHECK_VALUE, checkValue);
}
return CKR_OK;
}
/*****************************************
* CKA_SUBJECT
*****************************************/
// Set default value
bool P11AttrSubject::setDefault()
{
OSAttribute attr(ByteString(""));
return osobject->setAttribute(type, attr);
}
/*****************************************
* CKA_ISSUER
*****************************************/
// Set default value
bool P11AttrIssuer::setDefault()
{
OSAttribute attr(ByteString(""));
return osobject->setAttribute(type, attr);
}
/*****************************************
* CKA_TRUSTED
*****************************************/
// Set default value
bool P11AttrTrusted::setDefault()
{
OSAttribute attr(false);
return osobject->setAttribute(type, attr);
}
// Update the value if allowed
CK_RV P11AttrTrusted::updateAttr(Token *token, bool /*isPrivate*/, CK_VOID_PTR pValue, CK_ULONG ulValueLen, int /*op*/)
{
OSAttribute attrTrue(true);
OSAttribute attrFalse(false);
// Attribute specific checks
if (ulValueLen !=sizeof(CK_BBOOL))
{
return CKR_ATTRIBUTE_VALUE_INVALID;
}
// Store data
if (*(CK_BBOOL*)pValue == CK_FALSE)
{
osobject->setAttribute(type, attrFalse);
}
else
{
if (!token->isSOLoggedIn())
{
ERROR_MSG("CKA_TRUSTED can only be set to true by the SO");
return CKR_ATTRIBUTE_READ_ONLY;
}
osobject->setAttribute(type, attrTrue);
}
return CKR_OK;
}
/*****************************************
* CKA_CERTIFICATE_CATEGORY
*****************************************/
// Set default value
bool P11AttrCertificateCategory::setDefault()
{
OSAttribute attr((unsigned long)0);
return osobject->setAttribute(type, attr);
}
// Update the value if allowed
CK_RV P11AttrCertificateCategory::updateAttr(Token* /*token*/, bool /*isPrivate*/, CK_VOID_PTR pValue, CK_ULONG ulValueLen, int /*op*/)
{
// Attribute specific checks
if (ulValueLen !=sizeof(CK_ULONG))
{
return CKR_ATTRIBUTE_VALUE_INVALID;
}
// Store data
osobject->setAttribute(type, *(CK_ULONG*)pValue);
return CKR_OK;
}
/*****************************************
* CKA_START_DATE
*****************************************/
// Set default value
bool P11AttrStartDate::setDefault()
{
OSAttribute attr(ByteString(""));
return osobject->setAttribute(type, attr);
}
// Update the value if allowed
CK_RV P11AttrStartDate::updateAttr(Token* /*token*/, bool /*isPrivate*/, CK_VOID_PTR pValue, CK_ULONG ulValueLen, int /*op*/)
{
// Attribute specific checks
if (ulValueLen !=sizeof(CK_DATE) && ulValueLen !=0)
{
return CKR_ATTRIBUTE_VALUE_INVALID;
}
// Store data
osobject->setAttribute(type, ByteString((unsigned char*)pValue, ulValueLen));
return CKR_OK;
}
/*****************************************
* CKA_END_DATE
*****************************************/
// Set default value
bool P11AttrEndDate::setDefault()
{
OSAttribute attr(ByteString(""));
return osobject->setAttribute(type, attr);
}
// Update the value if allowed
CK_RV P11AttrEndDate::updateAttr(Token* /*token*/, bool /*isPrivate*/, CK_VOID_PTR pValue, CK_ULONG ulValueLen, int /*op*/)
{
// Attribute specific checks
if (ulValueLen !=sizeof(CK_DATE) && ulValueLen !=0)
{
return CKR_ATTRIBUTE_VALUE_INVALID;
}
// Store data
osobject->setAttribute(type, ByteString((unsigned char*)pValue, ulValueLen));
return CKR_OK;
}
/*****************************************
* CKA_SERIAL_NUMBER
*****************************************/
// Set default value
bool P11AttrSerialNumber::setDefault()
{
OSAttribute attr(ByteString(""));
return osobject->setAttribute(type, attr);
}
/*****************************************
* CKA_URL
*****************************************/
// Set default value
bool P11AttrURL::setDefault()
{
OSAttribute attr(ByteString(""));
return osobject->setAttribute(type, attr);
}
/*****************************************
* CKA_HASH_OF_SUBJECT_PUBLIC_KEY
*****************************************/
// Set default value
bool P11AttrHashOfSubjectPublicKey::setDefault()
{
OSAttribute attr(ByteString(""));
return osobject->setAttribute(type, attr);
}
/*****************************************
* CKA_HASH_OF_ISSUER_PUBLIC_KEY
*****************************************/
// Set default value
bool P11AttrHashOfIssuerPublicKey::setDefault()
{
OSAttribute attr(ByteString(""));
return osobject->setAttribute(type, attr);
}
/*****************************************
* CKA_JAVA_MIDP_SECURITY_DOMAIN
*****************************************/
// Set default value
bool P11AttrJavaMidpSecurityDomain::setDefault()
{
OSAttribute attr((unsigned long)0);
return osobject->setAttribute(type, attr);
}
// Update the value if allowed
CK_RV P11AttrJavaMidpSecurityDomain::updateAttr(Token* /*token*/, bool /*isPrivate*/, CK_VOID_PTR pValue, CK_ULONG ulValueLen, int /*op*/)
{
// Attribute specific checks
if (ulValueLen !=sizeof(CK_ULONG))
{
return CKR_ATTRIBUTE_VALUE_INVALID;
}
// Store data
osobject->setAttribute(type, *(CK_ULONG*)pValue);
return CKR_OK;
}
/*****************************************
* CKA_NAME_HASH_ALGORITHM
*****************************************/
// Set default value
bool P11AttrNameHashAlgorithm::setDefault()
{
OSAttribute attr((unsigned long)CKM_SHA_1);
return osobject->setAttribute(type, attr);
}
// Update the value if allowed
CK_RV P11AttrNameHashAlgorithm::updateAttr(Token* /*token*/, bool /*isPrivate*/, CK_VOID_PTR pValue, CK_ULONG ulValueLen, int /*op*/)
{
// Attribute specific checks
if (ulValueLen !=sizeof(CK_ULONG))
{
return CKR_ATTRIBUTE_VALUE_INVALID;
}
// Store data
osobject->setAttribute(type, *(CK_ULONG*)pValue);
return CKR_OK;
}
/*****************************************
* CKA_DERIVE
*****************************************/
// Set default value
bool P11AttrDerive::setDefault()
{
OSAttribute attr(false);
return osobject->setAttribute(type, attr);
}
// Update the value if allowed
CK_RV P11AttrDerive::updateAttr(Token* /*token*/, bool /*isPrivate*/, CK_VOID_PTR pValue, CK_ULONG ulValueLen, int /*op*/)
{
OSAttribute attrTrue(true);
OSAttribute attrFalse(false);
// Attribute specific checks
if (ulValueLen !=sizeof(CK_BBOOL))
{
return CKR_ATTRIBUTE_VALUE_INVALID;
}
// Store data
if (*(CK_BBOOL*)pValue == CK_FALSE)
{
osobject->setAttribute(type, attrFalse);
}
else
{
osobject->setAttribute(type, attrTrue);
}
return CKR_OK;
}
/*****************************************
* CKA_ENCRYPT
*****************************************/
// Set default value
bool P11AttrEncrypt::setDefault()
{
OSAttribute attr(true);
return osobject->setAttribute(type, attr);
}
// Update the value if allowed
CK_RV P11AttrEncrypt::updateAttr(Token* /*token*/, bool /*isPrivate*/, CK_VOID_PTR pValue, CK_ULONG ulValueLen, int /*op*/)
{
OSAttribute attrTrue(true);
OSAttribute attrFalse(false);
// Attribute specific checks
if (ulValueLen !=sizeof(CK_BBOOL))
{
return CKR_ATTRIBUTE_VALUE_INVALID;
}
// Store data
if (*(CK_BBOOL*)pValue == CK_FALSE)
{
osobject->setAttribute(type, attrFalse);
}
else
{
osobject->setAttribute(type, attrTrue);
}
return CKR_OK;
}
/*****************************************
* CKA_VERIFY
*****************************************/
// Set default value
bool P11AttrVerify::setDefault()
{
OSAttribute attr(true);
return osobject->setAttribute(type, attr);
}
// Update the value if allowed
CK_RV P11AttrVerify::updateAttr(Token* /*token*/, bool /*isPrivate*/, CK_VOID_PTR pValue, CK_ULONG ulValueLen, int /*op*/)
{
OSAttribute attrTrue(true);
OSAttribute attrFalse(false);
// Attribute specific checks
if (ulValueLen !=sizeof(CK_BBOOL))
{
return CKR_ATTRIBUTE_VALUE_INVALID;
}
// Store data
if (*(CK_BBOOL*)pValue == CK_FALSE)
{
osobject->setAttribute(type, attrFalse);
}
else
{
osobject->setAttribute(type, attrTrue);
}
return CKR_OK;
}
/*****************************************
* CKA_VERIFY_RECOVER
*****************************************/
// Set default value
bool P11AttrVerifyRecover::setDefault()
{
OSAttribute attr(true);
return osobject->setAttribute(type, attr);
}
// Update the value if allowed
CK_RV P11AttrVerifyRecover::updateAttr(Token* /*token*/, bool /*isPrivate*/, CK_VOID_PTR pValue, CK_ULONG ulValueLen, int /*op*/)
{
OSAttribute attrTrue(true);
OSAttribute attrFalse(false);
// Attribute specific checks
if (ulValueLen !=sizeof(CK_BBOOL))
{
return CKR_ATTRIBUTE_VALUE_INVALID;
}
// Store data
if (*(CK_BBOOL*)pValue == CK_FALSE)
{
osobject->setAttribute(type, attrFalse);
}
else
{
osobject->setAttribute(type, attrTrue);
}
return CKR_OK;
}
/*****************************************
* CKA_WRAP
*****************************************/
// Set default value
bool P11AttrWrap::setDefault()
{
OSAttribute attr(true);
return osobject->setAttribute(type, attr);
}
// Update the value if allowed
CK_RV P11AttrWrap::updateAttr(Token* /*token*/, bool /*isPrivate*/, CK_VOID_PTR pValue, CK_ULONG ulValueLen, int /*op*/)
{
OSAttribute attrTrue(true);
OSAttribute attrFalse(false);
// Attribute specific checks
if (ulValueLen !=sizeof(CK_BBOOL))
{
return CKR_ATTRIBUTE_VALUE_INVALID;
}
// Store data
if (*(CK_BBOOL*)pValue == CK_FALSE)
{
osobject->setAttribute(type, attrFalse);
}
else
{
osobject->setAttribute(type, attrTrue);
}
return CKR_OK;
}
/*****************************************
* CKA_DECRYPT
*****************************************/
// Set default value
bool P11AttrDecrypt::setDefault()
{
OSAttribute attr(true);
return osobject->setAttribute(type, attr);
}
// Update the value if allowed
CK_RV P11AttrDecrypt::updateAttr(Token* /*token*/, bool /*isPrivate*/, CK_VOID_PTR pValue, CK_ULONG ulValueLen, int /*op*/)
{
OSAttribute attrTrue(true);
OSAttribute attrFalse(false);
// Attribute specific checks
if (ulValueLen !=sizeof(CK_BBOOL))
{
return CKR_ATTRIBUTE_VALUE_INVALID;
}
// Store data
if (*(CK_BBOOL*)pValue == CK_FALSE)
{
osobject->setAttribute(type, attrFalse);
}
else
{
osobject->setAttribute(type, attrTrue);
}
return CKR_OK;
}
/*****************************************
* CKA_SIGN
*****************************************/
// Set default value
bool P11AttrSign::setDefault()
{
OSAttribute attr(true);
return osobject->setAttribute(type, attr);
}
// Update the value if allowed
CK_RV P11AttrSign::updateAttr(Token* /*token*/, bool /*isPrivate*/, CK_VOID_PTR pValue, CK_ULONG ulValueLen, int /*op*/)
{
OSAttribute attrTrue(true);
OSAttribute attrFalse(false);
// Attribute specific checks
if (ulValueLen !=sizeof(CK_BBOOL))
{
return CKR_ATTRIBUTE_VALUE_INVALID;
}
// Store data
if (*(CK_BBOOL*)pValue == CK_FALSE)
{
osobject->setAttribute(type, attrFalse);
}
else
{
osobject->setAttribute(type, attrTrue);
}
return CKR_OK;
}
/*****************************************
* CKA_SIGN_RECOVER
*****************************************/
// Set default value
bool P11AttrSignRecover::setDefault()
{
OSAttribute attr(true);
return osobject->setAttribute(type, attr);
}
// Update the value if allowed
CK_RV P11AttrSignRecover::updateAttr(Token* /*token*/, bool /*isPrivate*/, CK_VOID_PTR pValue, CK_ULONG ulValueLen, int /*op*/)
{
OSAttribute attrTrue(true);
OSAttribute attrFalse(false);
// Attribute specific checks
if (ulValueLen !=sizeof(CK_BBOOL))
{
return CKR_ATTRIBUTE_VALUE_INVALID;
}
// Store data
if (*(CK_BBOOL*)pValue == CK_FALSE)
{
osobject->setAttribute(type, attrFalse);
}
else
{
osobject->setAttribute(type, attrTrue);
}
return CKR_OK;
}
/*****************************************
* CKA_UNWRAP
*****************************************/
// Set default value
bool P11AttrUnwrap::setDefault()
{
OSAttribute attr(true);
return osobject->setAttribute(type, attr);
}
// Update the value if allowed
CK_RV P11AttrUnwrap::updateAttr(Token* /*token*/, bool /*isPrivate*/, CK_VOID_PTR pValue, CK_ULONG ulValueLen, int /*op*/)
{
OSAttribute attrTrue(true);
OSAttribute attrFalse(false);
// Attribute specific checks
if (ulValueLen !=sizeof(CK_BBOOL))
{
return CKR_ATTRIBUTE_VALUE_INVALID;
}
// Store data
if (*(CK_BBOOL*)pValue == CK_FALSE)
{
osobject->setAttribute(type, attrFalse);
}
else
{
osobject->setAttribute(type, attrTrue);
}
return CKR_OK;
}
/*****************************************
* CKA_LOCAL
*****************************************/
// Set default value
bool P11AttrLocal::setDefault()
{
OSAttribute attr(false);
return osobject->setAttribute(type, attr);
}
// Update the value if allowed
CK_RV P11AttrLocal::updateAttr(Token* /*token*/, bool /*isPrivate*/, CK_VOID_PTR /*pValue*/, CK_ULONG /*ulValueLen*/, int /*op*/)
{
return CKR_ATTRIBUTE_READ_ONLY;
}
/*****************************************
* CKA_KEY_GEN_MECHANISM
*****************************************/
// Set default value
bool P11AttrKeyGenMechanism::setDefault()
{
OSAttribute attr((unsigned long)CK_UNAVAILABLE_INFORMATION);
return osobject->setAttribute(type, attr);
}
// Update the value if allowed
CK_RV P11AttrKeyGenMechanism::updateAttr(Token* /*token*/, bool /*isPrivate*/, CK_VOID_PTR /*pValue*/, CK_ULONG /*ulValueLen*/, int /*op*/)
{
return CKR_ATTRIBUTE_READ_ONLY;
}
/*****************************************
* CKA_ALWAYS_SENSITIVE
*****************************************/
// Set default value
bool P11AttrAlwaysSensitive::setDefault()
{
OSAttribute attr(false);
return osobject->setAttribute(type, attr);
}
// Update the value if allowed
CK_RV P11AttrAlwaysSensitive::updateAttr(Token* /*token*/, bool /*isPrivate*/, CK_VOID_PTR /*pValue*/, CK_ULONG /*ulValueLen*/, int /*op*/)
{
return CKR_ATTRIBUTE_READ_ONLY;
}
/*****************************************
* CKA_NEVER_EXTRACTABLE
*****************************************/
// Set default value
bool P11AttrNeverExtractable::setDefault()
{
OSAttribute attr(true);
return osobject->setAttribute(type, attr);
}
// Update the value if allowed
CK_RV P11AttrNeverExtractable::updateAttr(Token* /*token*/, bool /*isPrivate*/, CK_VOID_PTR /*pValue*/, CK_ULONG /*ulValueLen*/, int /*op*/)
{
return CKR_ATTRIBUTE_READ_ONLY;
}
/*****************************************
* CKA_SENSITIVE
*****************************************/
// Set default value
bool P11AttrSensitive::setDefault()
{
// We default to false because we want to handle the secret keys in a correct way
OSAttribute attr(false);
return osobject->setAttribute(type, attr);
}
// Update the value if allowed
CK_RV P11AttrSensitive::updateAttr(Token* /*token*/, bool /*isPrivate*/, CK_VOID_PTR pValue, CK_ULONG ulValueLen, int op)
{
OSAttribute attrTrue(true);
OSAttribute attrFalse(false);
// Attribute specific checks
if (op == OBJECT_OP_SET || op == OBJECT_OP_COPY)
{
if (osobject->getBooleanValue(CKA_SENSITIVE, false))
{
return CKR_ATTRIBUTE_READ_ONLY;
}
}
if (ulValueLen !=sizeof(CK_BBOOL))
{
return CKR_ATTRIBUTE_VALUE_INVALID;
}
// Store data
if (*(CK_BBOOL*)pValue == CK_FALSE)
{
osobject->setAttribute(type, attrFalse);
osobject->setAttribute(CKA_ALWAYS_SENSITIVE, attrFalse);
}
else
{
osobject->setAttribute(type, attrTrue);
// This is so that generated keys get the correct value
if (op == OBJECT_OP_GENERATE || op == OBJECT_OP_DERIVE)
{
osobject->setAttribute(CKA_ALWAYS_SENSITIVE, attrTrue);
}
}
return CKR_OK;
}
/*****************************************
* CKA_EXTRACTABLE
*****************************************/
// Set default value
bool P11AttrExtractable::setDefault()
{
OSAttribute attr(false);
return osobject->setAttribute(type, attr);
}
// Update the value if allowed
CK_RV P11AttrExtractable::updateAttr(Token* /*token*/, bool /*isPrivate*/, CK_VOID_PTR pValue, CK_ULONG ulValueLen, int op)
{
OSAttribute attrTrue(true);
OSAttribute attrFalse(false);
// Attribute specific checks
if (op == OBJECT_OP_SET || op == OBJECT_OP_COPY)
{
if (osobject->getBooleanValue(CKA_EXTRACTABLE, false) == false)
{
return CKR_ATTRIBUTE_READ_ONLY;
}
}
if (ulValueLen !=sizeof(CK_BBOOL))
{
return CKR_ATTRIBUTE_VALUE_INVALID;
}
// Store data
if (*(CK_BBOOL*)pValue == CK_FALSE)
{
osobject->setAttribute(type, attrFalse);
}
else
{
osobject->setAttribute(type, attrTrue);
osobject->setAttribute(CKA_NEVER_EXTRACTABLE, attrFalse);
}
return CKR_OK;
}
/*****************************************
* CKA_WRAP_WITH_TRUSTED
*****************************************/
// Set default value
bool P11AttrWrapWithTrusted::setDefault()
{
OSAttribute attr(false);
return osobject->setAttribute(type, attr);
}
// Update the value if allowed
CK_RV P11AttrWrapWithTrusted::updateAttr(Token* /*token*/, bool /*isPrivate*/, CK_VOID_PTR pValue, CK_ULONG ulValueLen, int op)
{
OSAttribute attrTrue(true);
OSAttribute attrFalse(false);
// Attribute specific checks
if (op == OBJECT_OP_SET || op == OBJECT_OP_COPY)
{
if (osobject->getBooleanValue(CKA_WRAP_WITH_TRUSTED, false))
{
return CKR_ATTRIBUTE_READ_ONLY;
}
}
if (ulValueLen !=sizeof(CK_BBOOL))
{
return CKR_ATTRIBUTE_VALUE_INVALID;
}
// Store data
if (*(CK_BBOOL*)pValue == CK_FALSE)
{
osobject->setAttribute(type, attrFalse);
}
else
{
osobject->setAttribute(type, attrTrue);
}
return CKR_OK;
}
/*****************************************
* CKA_ALWAYS_AUTHENTICATE
*****************************************/
// Set default value
bool P11AttrAlwaysAuthenticate::setDefault()
{
OSAttribute attr(false);
return osobject->setAttribute(type, attr);
}
// Update the value if allowed
CK_RV P11AttrAlwaysAuthenticate::updateAttr(Token* /*token*/, bool isPrivate, CK_VOID_PTR pValue, CK_ULONG ulValueLen, int /*op*/)
{
OSAttribute attrTrue(true);
OSAttribute attrFalse(false);
// Attribute specific checks
if (ulValueLen !=sizeof(CK_BBOOL))
{
return CKR_ATTRIBUTE_VALUE_INVALID;
}
// Store data
if (*(CK_BBOOL*)pValue == CK_FALSE)
{
osobject->setAttribute(type, attrFalse);
}
else
{
if (!isPrivate)
{
return CKR_TEMPLATE_INCONSISTENT;
}
osobject->setAttribute(type, attrTrue);
}
return CKR_OK;
}
/*****************************************
* CKA_MODULUS
*****************************************/
// Set default value
bool P11AttrModulus::setDefault()
{
OSAttribute attr(ByteString(""));
return osobject->setAttribute(type, attr);
}
// Update the value if allowed
CK_RV P11AttrModulus::updateAttr(Token *token, bool isPrivate, CK_VOID_PTR pValue, CK_ULONG ulValueLen, int op)
{
ByteString plaintext((unsigned char*)pValue, ulValueLen);
ByteString value;
// Encrypt
if (isPrivate)
{
if (!token->encrypt(plaintext, value))
return CKR_GENERAL_ERROR;
}
else
value = plaintext;
// Attribute specific checks
if (value.size() < ulValueLen)
return CKR_GENERAL_ERROR;
// Store data
osobject->setAttribute(type, value);
// Set the CKA_MODULUS_BITS during C_CreateObject
if (op == OBJECT_OP_CREATE && osobject->attributeExists(CKA_MODULUS_BITS))
{
OSAttribute bits((unsigned long)plaintext.bits());
osobject->setAttribute(CKA_MODULUS_BITS, bits);
}
return CKR_OK;
}
/*****************************************
* CKA_PUBLIC_EXPONENT
*****************************************/
// Set default value
bool P11AttrPublicExponent::setDefault()
{
OSAttribute attr(ByteString(""));
return osobject->setAttribute(type, attr);
}
/*****************************************
* CKA_PRIVATE_EXPONENT
*****************************************/
// Set default value
bool P11AttrPrivateExponent::setDefault()
{
OSAttribute attr(ByteString(""));
return osobject->setAttribute(type, attr);
}
/*****************************************
* CKA_PRIME_1
*****************************************/
// Set default value
bool P11AttrPrime1::setDefault()
{
OSAttribute attr(ByteString(""));
return osobject->setAttribute(type, attr);
}
/*****************************************
* CKA_PRIME_2
*****************************************/
// Set default value
bool P11AttrPrime2::setDefault()
{
OSAttribute attr(ByteString(""));
return osobject->setAttribute(type, attr);
}
/*****************************************
* CKA_EXPONENT_1
*****************************************/
// Set default value
bool P11AttrExponent1::setDefault()
{
OSAttribute attr(ByteString(""));
return osobject->setAttribute(type, attr);
}
/*****************************************
* CKA_EXPONENT_2
*****************************************/
// Set default value
bool P11AttrExponent2::setDefault()
{
OSAttribute attr(ByteString(""));
return osobject->setAttribute(type, attr);
}
/*****************************************
* CKA_COEFFICIENT
*****************************************/
// Set default value
bool P11AttrCoefficient::setDefault()
{
OSAttribute attr(ByteString(""));
return osobject->setAttribute(type, attr);
}
/*****************************************
* CKA_MODULUS_BITS
*****************************************/
// Set default value
bool P11AttrModulusBits::setDefault()
{
OSAttribute attr((unsigned long)0);
return osobject->setAttribute(type, attr);
}
// Update the value if allowed
CK_RV P11AttrModulusBits::updateAttr(Token* /*token*/, bool /*isPrivate*/, CK_VOID_PTR pValue, CK_ULONG ulValueLen, int op)
{
// Attribute specific checks
if (op != OBJECT_OP_GENERATE)
{
return CKR_ATTRIBUTE_READ_ONLY;
}
if (ulValueLen !=sizeof(CK_ULONG))
{
return CKR_ATTRIBUTE_VALUE_INVALID;
}
// Store data
osobject->setAttribute(type, *(CK_ULONG*)pValue);
return CKR_OK;
}
/*****************************************
* CKA_PRIME
*****************************************/
// Set default value
bool P11AttrPrime::setDefault()
{
OSAttribute attr(ByteString(""));
return osobject->setAttribute(type, attr);
}
// Update the value if allowed
CK_RV P11AttrPrime::updateAttr(Token *token, bool isPrivate, CK_VOID_PTR pValue, CK_ULONG ulValueLen, int op)
{
ByteString plaintext((unsigned char*)pValue, ulValueLen);
ByteString value;
// Encrypt
if (isPrivate)
{
if (!token->encrypt(plaintext, value))
return CKR_GENERAL_ERROR;
}
else
value = plaintext;
// Attribute specific checks
if (value.size() < ulValueLen)
return CKR_GENERAL_ERROR;
// Store data
osobject->setAttribute(type, value);
// Set the CKA_PRIME_BITS during C_CreateObject
if (op == OBJECT_OP_CREATE && osobject->attributeExists(CKA_PRIME_BITS))
{
OSAttribute bits((unsigned long)plaintext.bits());
osobject->setAttribute(CKA_PRIME_BITS, bits);
}
return CKR_OK;
}
/*****************************************
* CKA_SUBPRIME
*****************************************/
// Set default value
bool P11AttrSubPrime::setDefault()
{
OSAttribute attr(ByteString(""));
return osobject->setAttribute(type, attr);
}
/*****************************************
* CKA_BASE
*****************************************/
// Set default value
bool P11AttrBase::setDefault()
{
OSAttribute attr(ByteString(""));
return osobject->setAttribute(type, attr);
}
/*****************************************
* CKA_PRIME_BITS
*****************************************/
// Set default value
bool P11AttrPrimeBits::setDefault()
{
OSAttribute attr((unsigned long)0);
return osobject->setAttribute(type, attr);
}
// Update the value if allowed
CK_RV P11AttrPrimeBits::updateAttr(Token* /*token*/, bool /*isPrivate*/, CK_VOID_PTR pValue, CK_ULONG ulValueLen, int op)
{
// Attribute specific checks
if (op != OBJECT_OP_GENERATE)
{
return CKR_ATTRIBUTE_READ_ONLY;
}
if (ulValueLen != sizeof(CK_ULONG))
{
return CKR_ATTRIBUTE_VALUE_INVALID;
}
// Store data
osobject->setAttribute(type, *(CK_ULONG*)pValue);
return CKR_OK;
}
/*****************************************
* CKA_VALUE_BITS
*****************************************/
// Set default value
bool P11AttrValueBits::setDefault()
{
OSAttribute attr((unsigned long)0);
return osobject->setAttribute(type, attr);
}
// Update the value if allowed
CK_RV P11AttrValueBits::updateAttr(Token* /*token*/, bool /*isPrivate*/, CK_VOID_PTR pValue, CK_ULONG ulValueLen, int op)
{
// Attribute specific checks
if (op != OBJECT_OP_GENERATE)
{
return CKR_ATTRIBUTE_READ_ONLY;
}
if (ulValueLen != sizeof(CK_ULONG))
{
return CKR_ATTRIBUTE_VALUE_INVALID;
}
// Store data
osobject->setAttribute(type, *(CK_ULONG*)pValue);
return CKR_OK;
}
/*****************************************
* CKA_EC_PARAMS
*****************************************/
// Set default value
bool P11AttrEcParams::setDefault()
{
OSAttribute attr(ByteString(""));
return osobject->setAttribute(type, attr);
}
/*****************************************
* CKA_EC_POINT
*****************************************/
// Set default value
bool P11AttrEcPoint::setDefault()
{
OSAttribute attr(ByteString(""));
return osobject->setAttribute(type, attr);
}
/*****************************************
* CKA_GOSTR3410_PARAMS
*****************************************/
// Set default value
bool P11AttrGostR3410Params::setDefault()
{
OSAttribute attr(ByteString(""));
return osobject->setAttribute(type, attr);
}
/*****************************************
* CKA_GOSTR3411_PARAMS
*****************************************/
// Set default value
bool P11AttrGostR3411Params::setDefault()
{
OSAttribute attr(ByteString(""));
return osobject->setAttribute(type, attr);
}
/*****************************************
* CKA_GOST28147_PARAMS
*****************************************/
// Set default value
bool P11AttrGost28147Params::setDefault()
{
OSAttribute attr(ByteString(""));
return osobject->setAttribute(type, attr);
}
/*****************************************
* CKA_VALUE_LEN
*****************************************/
// Set default value
bool P11AttrValueLen::setDefault()
{
OSAttribute attr((unsigned long)0);
return osobject->setAttribute(type, attr);
}
// Update the value if allowed
CK_RV P11AttrValueLen::updateAttr(Token* /*token*/, bool /*isPrivate*/, CK_VOID_PTR pValue, CK_ULONG ulValueLen, int op)
{
// Attribute specific checks
if (op != OBJECT_OP_GENERATE && op != OBJECT_OP_DERIVE)
{
return CKR_ATTRIBUTE_READ_ONLY;
}
if (ulValueLen != sizeof(CK_ULONG))
{
return CKR_ATTRIBUTE_VALUE_INVALID;
}
// Store data
osobject->setAttribute(type, *(CK_ULONG*)pValue);
return CKR_OK;
}
/*****************************************
* CKA_WRAP_TEMPLATE
*****************************************/
// Set default value
bool P11AttrWrapTemplate::setDefault()
{
std::map<CK_ATTRIBUTE_TYPE,OSAttribute> empty;
OSAttribute attr(empty);
return osobject->setAttribute(type, attr);
}
// Update the value
CK_RV P11AttrWrapTemplate::updateAttr(Token* /*token*/, bool /*isPrivate*/, CK_VOID_PTR pValue, CK_ULONG ulValueLen, int /*op*/)
{
// Attribute specific checks
if ((ulValueLen % sizeof(CK_ATTRIBUTE)) != 0)
{
return CKR_ATTRIBUTE_VALUE_INVALID;
}
// Fill the template vector with elements
CK_ATTRIBUTE_PTR attr = (CK_ATTRIBUTE_PTR) pValue;
std::map<CK_ATTRIBUTE_TYPE,OSAttribute> data;
for (size_t i = 0; i < ulValueLen / sizeof(CK_ATTRIBUTE); ++i, ++attr)
// Specialization for known attributes
switch (attr->type)
{
case CKA_TOKEN:
case CKA_PRIVATE:
case CKA_MODIFIABLE:
case CKA_COPYABLE:
case CKA_TRUSTED:
case CKA_ENCRYPT:
case CKA_DECRYPT:
case CKA_SIGN:
case CKA_SIGN_RECOVER:
case CKA_VERIFY:
case CKA_VERIFY_RECOVER:
case CKA_WRAP:
case CKA_UNWRAP:
case CKA_DERIVE:
case CKA_LOCAL:
case CKA_ALWAYS_SENSITIVE:
case CKA_SENSITIVE:
case CKA_NEVER_EXTRACTABLE:
case CKA_EXTRACTABLE:
case CKA_WRAP_WITH_TRUSTED:
case CKA_SECONDARY_AUTH:
case CKA_ALWAYS_AUTHENTICATE:
{
// CK_BBOOL
if (attr->ulValueLen != sizeof(CK_BBOOL))
return CKR_ATTRIBUTE_VALUE_INVALID;
bool elem = (*(CK_BBOOL*)attr->pValue != CK_FALSE);
data.insert(std::pair<CK_ATTRIBUTE_TYPE,OSAttribute> (attr->type, elem));
}
break;
case CKA_CLASS:
case CKA_KEY_TYPE:
case CKA_CERTIFICATE_TYPE:
case CKA_CERTIFICATE_CATEGORY:
case CKA_JAVA_MIDP_SECURITY_DOMAIN:
case CKA_NAME_HASH_ALGORITHM:
case CKA_KEY_GEN_MECHANISM:
case CKA_MODULUS_BITS:
case CKA_PRIME_BITS:
case CKA_SUB_PRIME_BITS:
case CKA_VALUE_BITS:
case CKA_VALUE_LEN:
case CKA_AUTH_PIN_FLAGS:
{
// CK_ULONG
if (attr->ulValueLen != sizeof(CK_ULONG))
return CKR_ATTRIBUTE_VALUE_INVALID;
unsigned long elem = *(CK_ULONG*)attr->pValue;
data.insert(std::pair<CK_ATTRIBUTE_TYPE,OSAttribute> (attr->type, elem));
}
break;
case CKA_WRAP_TEMPLATE:
case CKA_UNWRAP_TEMPLATE:
return CKR_ATTRIBUTE_VALUE_INVALID;
default:
{
// CK_BYTE
ByteString elem = ByteString((unsigned char*)attr->pValue, attr->ulValueLen);
data.insert(std::pair<CK_ATTRIBUTE_TYPE,OSAttribute> (attr->type, elem));
}
}
// Store data
osobject->setAttribute(type, data);
return CKR_OK;
}
/*****************************************
* CKA_UNWRAP_TEMPLATE
*****************************************/
// Set default value
bool P11AttrUnwrapTemplate::setDefault()
{
std::map<CK_ATTRIBUTE_TYPE,OSAttribute> empty;
OSAttribute attr(empty);
return osobject->setAttribute(type, attr);
}
// Update the value
CK_RV P11AttrUnwrapTemplate::updateAttr(Token* /*token*/, bool /*isPrivate*/, CK_VOID_PTR pValue, CK_ULONG ulValueLen, int /*op*/)
{
// Attribute specific checks
if ((ulValueLen % sizeof(CK_ATTRIBUTE)) != 0)
{
return CKR_ATTRIBUTE_VALUE_INVALID;
}
// Fill the template vector with elements
CK_ATTRIBUTE_PTR attr = (CK_ATTRIBUTE_PTR) pValue;
std::map<CK_ATTRIBUTE_TYPE,OSAttribute> data;
for (size_t i = 0; i < ulValueLen / sizeof(CK_ATTRIBUTE); ++i, ++attr)
// Specialization for known attributes
switch (attr->type)
{
case CKA_TOKEN:
case CKA_PRIVATE:
case CKA_MODIFIABLE:
case CKA_COPYABLE:
case CKA_TRUSTED:
case CKA_ENCRYPT:
case CKA_DECRYPT:
case CKA_SIGN:
case CKA_SIGN_RECOVER:
case CKA_VERIFY:
case CKA_VERIFY_RECOVER:
case CKA_WRAP:
case CKA_UNWRAP:
case CKA_DERIVE:
case CKA_LOCAL:
case CKA_ALWAYS_SENSITIVE:
case CKA_SENSITIVE:
case CKA_NEVER_EXTRACTABLE:
case CKA_EXTRACTABLE:
case CKA_WRAP_WITH_TRUSTED:
case CKA_SECONDARY_AUTH:
case CKA_ALWAYS_AUTHENTICATE:
{
// CK_BBOOL
if (attr->ulValueLen != sizeof(CK_BBOOL))
return CKR_ATTRIBUTE_VALUE_INVALID;
bool elem = (*(CK_BBOOL*)attr->pValue != CK_FALSE);
data.insert(std::pair<CK_ATTRIBUTE_TYPE,OSAttribute> (attr->type, elem));
}
break;
case CKA_CLASS:
case CKA_KEY_TYPE:
case CKA_CERTIFICATE_TYPE:
case CKA_CERTIFICATE_CATEGORY:
case CKA_JAVA_MIDP_SECURITY_DOMAIN:
case CKA_NAME_HASH_ALGORITHM:
case CKA_KEY_GEN_MECHANISM:
case CKA_MODULUS_BITS:
case CKA_PRIME_BITS:
case CKA_SUB_PRIME_BITS:
case CKA_VALUE_BITS:
case CKA_VALUE_LEN:
case CKA_AUTH_PIN_FLAGS:
{
// CK_ULONG
if (attr->ulValueLen != sizeof(CK_ULONG))
return CKR_ATTRIBUTE_VALUE_INVALID;
unsigned long elem = *(CK_ULONG*)attr->pValue;
data.insert(std::pair<CK_ATTRIBUTE_TYPE,OSAttribute> (attr->type, elem));
}
break;
case CKA_WRAP_TEMPLATE:
case CKA_UNWRAP_TEMPLATE:
return CKR_ATTRIBUTE_VALUE_INVALID;
default:
{
// CK_BYTE
ByteString elem = ByteString((unsigned char*)attr->pValue, attr->ulValueLen);
data.insert(std::pair<CK_ATTRIBUTE_TYPE,OSAttribute> (attr->type, elem));
}
}
// Store data
osobject->setAttribute(type, data);
return CKR_OK;
}
/*****************************************
* CKA_ALLOWED_MECHANISMS
*****************************************/
// Set default value
bool P11AttrAllowedMechanisms::setDefault()
{
std::set<CK_MECHANISM_TYPE> emptyMap;
return osobject->setAttribute(type, OSAttribute(emptyMap));
}
// Update the value if allowed
CK_RV P11AttrAllowedMechanisms::updateAttr(Token* /*token*/, bool /*isPrivate*/, CK_VOID_PTR pValue, CK_ULONG ulValueLen, int /*op*/)
{
if (ulValueLen == 0 || (ulValueLen % sizeof(CK_MECHANISM_TYPE)) != 0)
{
return CKR_ATTRIBUTE_VALUE_INVALID;
}
CK_MECHANISM_TYPE_PTR mechType = (CK_MECHANISM_TYPE_PTR) pValue;
// Fill the set with values
std::set<CK_MECHANISM_TYPE> data;
for (size_t i = 0; i < ulValueLen / sizeof(CK_MECHANISM_TYPE); ++i, ++mechType)
{
data.insert(*mechType);
}
// Store data
osobject->setAttribute(type, OSAttribute(data));
return CKR_OK;
}
// Set default value
bool P11AttrPrivateHandle::setDefault()
{
OSAttribute attr((CK_ULONG)0);
return osobject->setAttribute(type, attr);
}
// Update the value if allowed
CK_RV P11AttrPrivateHandle::updateAttr(Token* /*token*/, bool /*isPrivate*/, CK_VOID_PTR pValue, CK_ULONG ulValueLen, int op)
{
// Attribute specific checks
if (op != OBJECT_OP_CREATE)
{
return CKR_ATTRIBUTE_READ_ONLY;
}
if (ulValueLen !=sizeof(CK_ULONG))
{
return CKR_ATTRIBUTE_VALUE_INVALID;
}
// Store data
osobject->setAttribute(type, *((CK_ULONG*)pValue));
return CKR_OK;
}