diff options
Diffstat (limited to 'SoftHSMv2/src/lib/P11Attributes.cpp')
-rw-r--r-- | SoftHSMv2/src/lib/P11Attributes.cpp | 2514 |
1 files changed, 2514 insertions, 0 deletions
diff --git a/SoftHSMv2/src/lib/P11Attributes.cpp b/SoftHSMv2/src/lib/P11Attributes.cpp new file mode 100644 index 0000000..28d0f9b --- /dev/null +++ b/SoftHSMv2/src/lib/P11Attributes.cpp @@ -0,0 +1,2514 @@ +/* + * 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 + { + // 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_SUBPRIME_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_SUBPRIME_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; +} |