/* * 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 #include // 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& 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::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::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 set = attr.getMechanismTypeSetValue(); for (std::set::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 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 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 (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 (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 (attr->type, elem)); } } // Store data osobject->setAttribute(type, data); return CKR_OK; } /***************************************** * CKA_UNWRAP_TEMPLATE *****************************************/ // Set default value bool P11AttrUnwrapTemplate::setDefault() { std::map 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 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 (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 (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 (attr->type, elem)); } } // Store data osobject->setAttribute(type, data); return CKR_OK; } /***************************************** * CKA_ALLOWED_MECHANISMS *****************************************/ // Set default value bool P11AttrAllowedMechanisms::setDefault() { std::set 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 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; }