diff --git a/src/cryptoki.hxx b/src/cryptoki.hxx index 45cdd9c..9b61640 100644 --- a/src/cryptoki.hxx +++ b/src/cryptoki.hxx @@ -107,7 +107,7 @@ namespace cryptoki { typedef std::vector AttributeTypeList; struct Attribute { - Attribute(CK_ATTRIBUTE_TYPE t): type(t) {} + Attribute(CK_ATTRIBUTE_TYPE t = -1): type(t) {} Attribute(CK_ATTRIBUTE& attr): type(attr.type), value((char*)attr.pValue, attr.ulValueLen) { free(attr.pValue); @@ -549,8 +549,7 @@ namespace cryptoki { ~Init() { try { //! calls @c C_Finalize - return check(_slot._init->_fn->C_Finalize(0), - CRYPTOKI_FN_LOG("C_Finalize")); + check(_fn->C_Finalize(0), CRYPTOKI_FN_LOG("C_Finalize")); } catch (...) { if (!std::uncaught_exception()) throw; } @@ -997,7 +996,6 @@ namespace cryptoki { res.resize(size); return res; } - @endcode */ /*! @todo Not implemented: @code @@ -1369,91 +1367,153 @@ namespace cryptoki { } @endcode */ - AttributeMap attributes(AttributeTypeList attributes + + //! Get a Single Attribute + Attribute operator[](CK_ATTRIBUTE_TYPE a) { + return attribute(a); + } + + //! Get a Single Attribute + Attribute attribute(CK_ATTRIBUTE_TYPE a) { + Attribute res; + CK_ATTRIBUTE attr((CK_ATTRIBUTE){a, 0, 0}); + //! calls @c C_GetAttributeValue + if (!check(_session->_slot._init->_fn->C_GetAttributeValue + (_session->_session, _object, &attr, 1), + CRYPTOKI_FN_LOG("C_GetAttributeValue")) + || !(long)attr.ulValueLen>0l) + //! Without exception handling, size and type must be checked too. + return res; + try { + attr.pValue = malloc(attr.ulValueLen); + attr.pValue = memset(attr.pValue, 0, attr.ulValueLen); + if (check(_session->_slot._init->_fn->C_GetAttributeValue + (_session->_session, _object, &attr, 1), + CRYPTOKI_FN_LOG("C_GetAttributeValue"))) + /*! @todo There's no @c CKA_WRAP_TEMPLATE in Open + Cryptoki. From the Specs: «In the special case + of an attribute whose value is an array of + attributes, for example CKA_WRAP_TEMPLATE, where + it is passed in with pValue not NULL, then if + the pValue of elements within the array is + NULL_PTR then the ulValueLen of elements within + the array will be set to the required length. If + the pValue of elements within the array is not + NULL_PTR, then the ulValueLen element of + attributes within the array must reflect the + space that the corresponding pValue points to, + and pValue is filled in if there is sufficient + room. Therefore it is important to initialize + the contents of a buffer before calling + C_GetAttributeValue to get such an array + value. If any ulValueLen within the array isn't + large enough, it will be set to â��1 and the + function will return CKR_BUFFER_TOO_SMALL, as it + does if an attribute in the pTemplate argument + has ulValueLen too small. Note that any + attribute whose value is an array of attributes + is identifiable by virtue of the attribute type + having the CKF_ARRAY_ATTRIBUTE bit set.» */ + res = Attribute(attr); + else + free(attr.pValue); + } catch (...) { + free(attr.pValue); + throw; + } + return res; + } + + //! Get a List of Attributes. + /*! If @c attrs is empty, all available attributes are + returned. Attributes that cannot be accessed or that are not + available in this Object won't be in the result map. There + is no exception in this case. */ + AttributeMap attributes(AttributeTypeList attrs = AttributeTypeList()) { AttributeMap res; - //! Gets all attributes, if @c attributes is empty - if (attributes.empty()) { - attributes.push_back(CKA_CLASS); - attributes.push_back(CKA_TOKEN); - attributes.push_back(CKA_PRIVATE); - attributes.push_back(CKA_LABEL); - attributes.push_back(CKA_APPLICATION); - attributes.push_back(CKA_VALUE); - attributes.push_back(CKA_OBJECT_ID); - attributes.push_back(CKA_CERTIFICATE_TYPE); - attributes.push_back(CKA_ISSUER); - attributes.push_back(CKA_SERIAL_NUMBER); - attributes.push_back(CKA_AC_ISSUER); - attributes.push_back(CKA_OWNER); - attributes.push_back(CKA_ATTR_TYPES); - attributes.push_back(CKA_TRUSTED); - attributes.push_back(CKA_KEY_TYPE); - attributes.push_back(CKA_SUBJECT); - attributes.push_back(CKA_ID); - attributes.push_back(CKA_SENSITIVE); - attributes.push_back(CKA_ENCRYPT); - attributes.push_back(CKA_DECRYPT); - attributes.push_back(CKA_WRAP); - attributes.push_back(CKA_UNWRAP); - attributes.push_back(CKA_SIGN); - attributes.push_back(CKA_SIGN_RECOVER); - attributes.push_back(CKA_VERIFY); - attributes.push_back(CKA_VERIFY_RECOVER); - attributes.push_back(CKA_DERIVE); - attributes.push_back(CKA_START_DATE); - attributes.push_back(CKA_END_DATE); - attributes.push_back(CKA_MODULUS); - attributes.push_back(CKA_MODULUS_BITS); - attributes.push_back(CKA_PUBLIC_EXPONENT); - attributes.push_back(CKA_PRIVATE_EXPONENT); - attributes.push_back(CKA_PRIME_1); - attributes.push_back(CKA_PRIME_2); - attributes.push_back(CKA_EXPONENT_1); - attributes.push_back(CKA_EXPONENT_2); - attributes.push_back(CKA_COEFFICIENT); - attributes.push_back(CKA_PRIME); - attributes.push_back(CKA_SUBPRIME); - attributes.push_back(CKA_BASE); - attributes.push_back(CKA_PRIME_BITS); - attributes.push_back(CKA_SUBPRIME_BITS); - attributes.push_back(CKA_VALUE_BITS); - attributes.push_back(CKA_VALUE_LEN); - attributes.push_back(CKA_EXTRACTABLE); - attributes.push_back(CKA_LOCAL); - attributes.push_back(CKA_NEVER_EXTRACTABLE); - attributes.push_back(CKA_ALWAYS_SENSITIVE); - attributes.push_back(CKA_KEY_GEN_MECHANISM); - attributes.push_back(CKA_MODIFIABLE); - attributes.push_back(CKA_ECDSA_PARAMS); - attributes.push_back(CKA_EC_PARAMS); - attributes.push_back(CKA_EC_POINT); - attributes.push_back(CKA_SECONDARY_AUTH); - attributes.push_back(CKA_AUTH_PIN_FLAGS); - attributes.push_back(CKA_HW_FEATURE_TYPE); - attributes.push_back(CKA_RESET_ON_INIT); - attributes.push_back(CKA_HAS_RESET); - attributes.push_back(CKA_VENDOR_DEFINED); - attributes.push_back(CKA_IBM_OPAQUE); + //! Gets all attributes, if @c attrs is empty + if (attrs.empty()) { + attrs.push_back(CKA_CLASS); + attrs.push_back(CKA_TOKEN); + attrs.push_back(CKA_PRIVATE); + attrs.push_back(CKA_LABEL); + attrs.push_back(CKA_APPLICATION); + attrs.push_back(CKA_VALUE); + attrs.push_back(CKA_OBJECT_ID); + attrs.push_back(CKA_CERTIFICATE_TYPE); + attrs.push_back(CKA_ISSUER); + attrs.push_back(CKA_SERIAL_NUMBER); + attrs.push_back(CKA_AC_ISSUER); + attrs.push_back(CKA_OWNER); + attrs.push_back(CKA_ATTR_TYPES); + attrs.push_back(CKA_TRUSTED); + attrs.push_back(CKA_KEY_TYPE); + attrs.push_back(CKA_SUBJECT); + attrs.push_back(CKA_ID); + attrs.push_back(CKA_SENSITIVE); + attrs.push_back(CKA_ENCRYPT); + attrs.push_back(CKA_DECRYPT); + attrs.push_back(CKA_WRAP); + attrs.push_back(CKA_UNWRAP); + attrs.push_back(CKA_SIGN); + attrs.push_back(CKA_SIGN_RECOVER); + attrs.push_back(CKA_VERIFY); + attrs.push_back(CKA_VERIFY_RECOVER); + attrs.push_back(CKA_DERIVE); + attrs.push_back(CKA_START_DATE); + attrs.push_back(CKA_END_DATE); + attrs.push_back(CKA_MODULUS); + attrs.push_back(CKA_MODULUS_BITS); + attrs.push_back(CKA_PUBLIC_EXPONENT); + attrs.push_back(CKA_PRIVATE_EXPONENT); + attrs.push_back(CKA_PRIME_1); + attrs.push_back(CKA_PRIME_2); + attrs.push_back(CKA_EXPONENT_1); + attrs.push_back(CKA_EXPONENT_2); + attrs.push_back(CKA_COEFFICIENT); + attrs.push_back(CKA_PRIME); + attrs.push_back(CKA_SUBPRIME); + attrs.push_back(CKA_BASE); + attrs.push_back(CKA_PRIME_BITS); + attrs.push_back(CKA_SUBPRIME_BITS); + attrs.push_back(CKA_VALUE_BITS); + attrs.push_back(CKA_VALUE_LEN); + attrs.push_back(CKA_EXTRACTABLE); + attrs.push_back(CKA_LOCAL); + attrs.push_back(CKA_NEVER_EXTRACTABLE); + attrs.push_back(CKA_ALWAYS_SENSITIVE); + attrs.push_back(CKA_KEY_GEN_MECHANISM); + attrs.push_back(CKA_MODIFIABLE); + attrs.push_back(CKA_ECDSA_PARAMS); + attrs.push_back(CKA_EC_PARAMS); + attrs.push_back(CKA_EC_POINT); + attrs.push_back(CKA_SECONDARY_AUTH); + attrs.push_back(CKA_AUTH_PIN_FLAGS); + attrs.push_back(CKA_HW_FEATURE_TYPE); + attrs.push_back(CKA_RESET_ON_INIT); + attrs.push_back(CKA_HAS_RESET); + attrs.push_back(CKA_VENDOR_DEFINED); + attrs.push_back(CKA_IBM_OPAQUE); } - CK_ATTRIBUTE attrs; - for (AttributeTypeList::const_iterator it(attributes.begin()); - it!=attributes.end(); ++it) { - attrs = (CK_ATTRIBUTE){*it, 0, 0}; + CK_ATTRIBUTE attr; + for (AttributeTypeList::const_iterator it(attrs.begin()); + it!=attrs.end(); ++it) { + attr = (CK_ATTRIBUTE){*it, 0, 0}; try { //! calls @c C_GetAttributeValue if (_session->_slot._init->_fn->C_GetAttributeValue - (_session->_session, _object, &attrs, 1) + (_session->_session, _object, &attr, 1) == CKR_ATTRIBUTE_TYPE_INVALID || _res == CKR_ATTRIBUTE_SENSITIVE) { continue; //! Ignores unsupported Attributes. } else { check(_res, CRYPTOKI_FN_LOG("C_GetAttributeValue")); - if ((long)attrs.ulValueLen>0l) { - attrs.pValue = malloc(attrs.ulValueLen); - attrs.pValue = memset(attrs.pValue, 0, attrs.ulValueLen); + if ((long)attr.ulValueLen>0l) { + attr.pValue = malloc(attr.ulValueLen); + attr.pValue = memset(attr.pValue, 0, attr.ulValueLen); if (check(_session->_slot._init->_fn->C_GetAttributeValue - (_session->_session, _object, &attrs, 1), + (_session->_session, _object, &attr, 1), CRYPTOKI_FN_LOG("C_GetAttributeValue"))) /*! @todo There's no @c CKA_WRAP_TEMPLATE in Open Cryptoki. From the Specs: «In the special @@ -1483,10 +1543,10 @@ namespace cryptoki { attributes is identifiable by virtue of the attribute type having the CKF_ARRAY_ATTRIBUTE bit set.» */ - res.insert(std::make_pair(attrs.type, Attribute(attrs))); + res.insert(std::make_pair(attr.type, Attribute(attr))); else - free(attrs.pValue); - } else if (*it==CKA_MODULUS && attrs.ulValueLen==0) { + free(attr.pValue); + } else if (*it==CKA_MODULUS && attr.ulValueLen==0) { /*! @bug This is a bug in onepin-opensc-pkcs11.so: If @c CKA_MODULUS has a size of 0 bytes, the following query to @c CKA_MODULUS_BITS ends @@ -1498,41 +1558,15 @@ namespace cryptoki { CKA_MODULUS is 0 Bytes, the following attribute query is skipped as a work around to this bug. */ - if (++it==attributes.end()) break; + if (++it==attrs.end()) break; } } } catch (...) { - free(attrs.pValue); + free(attr.pValue); throw; } } return res; -// CK_ATTRIBUTE* attrs(new CK_ATTRIBUTE[attributes.size()]); -// AttributeTypeList::const_iterator it(attributes.begin()); -// for (AttributeTypeList::size_type i(0); it!=attributes.end(); ++it, ++i) -// attrs[i] = (CK_ATTRIBUTE){*it, 0, 0}; -// try { -// //! calls @c C_GetAttributeValue -// if (check(_session->_slot._init->_fn->C_GetAttributeValue -// (_session->_session, _object, attrs, attributes.size()), -// CRYPTOKI_FN_LOG("C_GetAttributeValue"))) { -// for (AttributeTypeList::size_type i(0); i0) -// attrs[i].pValue = malloc(attrs[i].ulValueLen); -// check(_session->_slot._init->_fn->C_GetAttributeValue -// (_session->_session, _object, attrs, attributes.size()), -// CRYPTOKI_FN_LOG("C_GetAttributeValue")); -// } -// for (AttributeTypeList::size_type i(0); i0) -// res.insert(std::make_pair(attrs[i].type, Attribute(attrs[i]))); -// return res; -// } catch (...) { -// for (AttributeTypeList::size_type i(0); i