diff options
author | Stef Walter <stef@memberwebs.com> | 2008-12-09 20:59:55 +0000 |
---|---|---|
committer | Stef Walter <stef@memberwebs.com> | 2008-12-09 20:59:55 +0000 |
commit | ae56e5c788e3ed6c60d98d445574d3042aaae24f (patch) | |
tree | 9b3acb30fbdfd9e791c81dafb895fd92b396ebfd /p11-capi-key.c | |
parent | 398b05acabebf6d882c0aaa94a4dfd3f5d6431d4 (diff) |
Move into module folder
Diffstat (limited to 'p11-capi-key.c')
-rw-r--r-- | p11-capi-key.c | 1083 |
1 files changed, 0 insertions, 1083 deletions
diff --git a/p11-capi-key.c b/p11-capi-key.c deleted file mode 100644 index ed306d4..0000000 --- a/p11-capi-key.c +++ /dev/null @@ -1,1083 +0,0 @@ -/* - * Copyright (C) 2008 Stef Walter - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -#include "p11-capi.h" -#include "p11-capi-cert.h" -#include "p11-capi-key.h" -#include "p11-capi-object.h" -#include "p11-capi-session.h" -#include "p11-capi-token.h" -#include "x509-usages.h" - -typedef struct _KeyObject -{ - P11cObject obj; - - /* The raw key identifier */ - CRYPT_HASH_BLOB key_identifier; - CK_OBJECT_CLASS object_class; -} -KeyObject; - -typedef struct _KeyObjectData -{ - P11cObjectData base; - CK_OBJECT_CLASS object_class; - CRYPT_INTEGER_BLOB key_identifier; - CRYPT_DATA_BLOB raw_public_key; - CRYPT_KEY_PROV_INFO* prov_info; -} -KeyObjectData; - -static CK_RV -load_key_handle(P11cObjectData* objdata, HCRYPTPROV* ret_prov, - HCRYPTKEY* ret_key) -{ - KeyObjectData* kdata = (KeyObjectData*)objdata; - HCRYPTPROV prov; - HCRYPTKEY key; - DWORD error; - - ASSERT(kdata); - ASSERT(ret_key); - ASSERT(ret_prov); - - if(!CryptAcquireContextW(&prov, kdata->prov_info->pwszContainerName, - kdata->prov_info->pwszProvName, - kdata->prov_info->dwProvType, 0)) - { - return p11c_winerr_to_ckr(GetLastError()); - } - - if(!CryptGetUserKey(prov, kdata->prov_info->dwKeySpec, &key)) - { - error = GetLastError(); - CryptReleaseContext(prov, 0); - return p11c_winerr_to_ckr(error); - } - - *ret_key = key; - *ret_prov = prov; - - return CKR_OK; -} - - -static CK_RV -load_raw_public_key(KeyObjectData* kdata) -{ - BOOL success = FALSE; - HCRYPTPROV prov; - HCRYPTKEY key; - CK_RV ret; - DWORD error; - - ASSERT(kdata); - ASSERT(!kdata->raw_public_key.pbData); - - ret = load_key_handle(&kdata->base, &prov, &key); - if(ret != CKR_OK) - return ret; - - if(CryptExportKey(key, 0, PUBLICKEYBLOB, 0, NULL, &kdata->raw_public_key.cbData)) - { - kdata->raw_public_key.pbData = malloc(kdata->raw_public_key.cbData); - if(!kdata->raw_public_key.pbData) - SetLastError(ERROR_NOT_ENOUGH_MEMORY); - else - { - if(CryptExportKey(key, 0, PUBLICKEYBLOB, 0, kdata->raw_public_key.pbData, - &kdata->raw_public_key.cbData)) - { - success = TRUE; - } - } - } - - CryptReleaseContext(prov, 0); - CryptDestroyKey(key); - - if(success) - { - return CKR_OK; - } - else - { - error = GetLastError(); - if(error == NTE_BAD_KEY_STATE) - return CKR_ATTRIBUTE_SENSITIVE; - return p11c_winerr_to_ckr(error); - } -} - -static CK_RV -lookup_rsa_attribute(KeyObjectData* kdata, CK_ATTRIBUTE_PTR attr) -{ - PUBLICKEYSTRUC* header; - RSAPUBKEY* pubkey; - CK_ULONG number; - CK_RV ret; - - ASSERT(kdata); - ASSERT(attr); - - if(!kdata->raw_public_key.pbData) - { - ret = load_raw_public_key(kdata); - if(ret != CKR_OK) - return ret; - } - - header = (PUBLICKEYSTRUC*)kdata->raw_public_key.pbData; - if(!header->bType == PUBLICKEYBLOB) - return CKR_GENERAL_ERROR; - - pubkey = (RSAPUBKEY*)(header + 1); - if(!pubkey->magic == 0x31415352) - return CKR_GENERAL_ERROR; - - switch(attr->type) - { - case CKA_MODULUS_BITS: - number = pubkey->bitlen; - return p11c_return_data(attr, &number, sizeof(CK_ULONG)); - - case CKA_PUBLIC_EXPONENT: - return p11c_return_dword_as_bytes(attr, pubkey->pubexp); - - case CKA_MODULUS: - return p11c_return_reversed_data(attr, (pubkey + 1), - pubkey->bitlen / 8); - - case CKA_PRIVATE_EXPONENT: - case CKA_PRIME_1: - case CKA_PRIME_2: - case CKA_EXPONENT_1: - case CKA_EXPONENT_2: - case CKA_COEFFICIENT: - if(kdata->object_class == CKO_PRIVATE_KEY) - return CKR_ATTRIBUTE_SENSITIVE; - else - return CKR_ATTRIBUTE_TYPE_INVALID; - - default: - ASSERT(FALSE); - return CKR_ATTRIBUTE_TYPE_INVALID; - } -} - -static CK_RV -key_bool_attribute(P11cObjectData* objdata, CK_ATTRIBUTE_PTR attr) -{ - KeyObjectData* kdata = (KeyObjectData*)objdata; - CK_BBOOL val; - CK_BBOOL is_private, is_rsa; - - ASSERT(objdata); - ASSERT(attr); - - is_private = (kdata->object_class == CKO_PRIVATE_KEY); - is_rsa = kdata->prov_info->dwProvType == PROV_RSA_FULL; - - switch(attr->type) - { - - /* - * Whether to authenticate before every use. - * - CAPI does all authentication - */ - case CKA_ALWAYS_AUTHENTICATE: - val = CK_FALSE; - break; - - /* - * Whether this key has always been sensitive. - * TODO: Can we detect this? - */ - case CKA_ALWAYS_SENSITIVE: - val = CK_FALSE; - break; - - /* - * Whether this key can be used to decrypt. - * - CKK_RSA but not CKK_DSA. - */ - case CKA_DECRYPT: - val = is_private && is_rsa; - break; - - /* - * Whether this key can be used to derive a session or - * other key. - * - Not true for CKK_RSA or CKK_DSA. - */ - case CKA_DERIVE: - val = CK_FALSE; - break; - - /* - * Whether or not this key can be used to encrypt?. - * TODO: Support for RSA public keys. - */ - case CKA_ENCRYPT: - val = CK_FALSE; - break; - - /* - * Whether this key can be exported or not. - * TODO: We may want to support this for public keys. - */ - case CKA_EXTRACTABLE: - val = CK_FALSE; - break; - - /* - * Whether this key was created on token. - * TODO: Can we implement this properly? - */ - case CKA_LOCAL: - val = CK_FALSE; - break; - - /* - * Whether this object is modifiable. - * - Keys are generally. never modifiable. - */ - case CKA_MODIFIABLE: - val = CK_FALSE; - break; - - /* - * Whether this key was ever extractable. - * TODO: Can we determine this? - */ - case CKA_NEVER_EXTRACTABLE: - val = CK_FALSE; - break; - - /* - * Whether this is a private object or not. - * - This 'private' means login before use. But maps - * well to private key use, since we're always logged in. - */ - case CKA_PRIVATE: - val = is_private; - break; - - /* - * Whether this is a sensitive object or not. - * - Private keys are sensitive, some attributes not - * readable. - */ - case CKA_SENSITIVE: - val = is_private; - break; - - /* - * Can this key sign stuff? - * - Private keys can sign. - */ - case CKA_SIGN: - val = is_private; - break; - - /* - * Can this key sign recoverable. - * TODO: Private RSA keys can sign recoverable. - */ - case CKA_SIGN_RECOVER: - val = CK_FALSE; - break; - - /* - * Is this stored on the token? - * - All CAPI objects are. - */ - case CKA_TOKEN: - val = CK_TRUE; - break; - - /* - * Is this key trusted? - * - A nebulous question. - */ - case CKA_TRUSTED: - val = CK_FALSE; - break; - - /* - * Key wrapping with public keys. - */ - case CKA_WRAP: - if(is_private) - return CKR_ATTRIBUTE_TYPE_INVALID; - val = CK_FALSE; - break; - - /* - * Key wrapping on private keys. - */ - case CKA_WRAP_WITH_TRUSTED: - if(!is_private) - return CKR_ATTRIBUTE_TYPE_INVALID; - val = CK_FALSE; - break; - - /* - * Can do a unwrap operation? - * - We don't implement this. - */ - case CKA_UNWRAP: - val = CK_FALSE; - break; - - /* - * Wrap, and unwrap stuff. - * - We don't implement this. - */ - case CKA_UNWRAP_TEMPLATE: - return CKR_ATTRIBUTE_TYPE_INVALID; - - /* - * Whether this key can be used to verify? - * TODO: Support for public keys. - */ - case CKA_VERIFY: - val = CK_FALSE; - break; - - /* - * Whether this key can be used to verify? - * TODO: Support for public keys. - */ - case CKA_VERIFY_RECOVER: - val = CK_FALSE; - break; - - default: - return CKR_ATTRIBUTE_TYPE_INVALID; - }; - - return p11c_return_data(attr, &val, sizeof(CK_BBOOL)); -} - -static CK_RV -key_ulong_attribute(P11cObjectData* objdata, CK_ATTRIBUTE_PTR attr) -{ - KeyObjectData* kdata = (KeyObjectData*)objdata; - CK_ULONG val; - - ASSERT(kdata); - ASSERT(attr); - - switch(attr->type) - { - - /* - * Object class. - */ - case CKA_CLASS: - val = kdata->object_class; - break; - - /* - * The key type. - * - Right now we only support (and load) RSA. - */ - case CKA_KEY_TYPE: - if(kdata->prov_info->dwProvType == PROV_RSA_FULL) - val = CKK_RSA; - else - val = CK_UNAVAILABLE_INFORMATION; - break; - - /* - * The key generation mechanism. - * TODO: We don't yet support key generation. - */ - case CKA_KEY_GEN_MECHANISM: - val = CK_UNAVAILABLE_INFORMATION; - break; - - /* - * The RSA modulus bits. - */ - case CKA_MODULUS_BITS: - if(kdata->prov_info->dwProvType == PROV_RSA_FULL) - return lookup_rsa_attribute(kdata, attr); - else - return CKR_ATTRIBUTE_TYPE_INVALID; - - default: - return CKR_ATTRIBUTE_TYPE_INVALID; - }; - - return p11c_return_data(attr, &val, sizeof(CK_ULONG)); -} - -static CK_RV -key_bytes_attribute(P11cObjectData* objdata, CK_ATTRIBUTE_PTR attr) -{ - KeyObjectData* kdata = (KeyObjectData*)objdata; - CK_MECHANISM_TYPE allowed_mechanisms[] = { CKM_RSA_PKCS }; - WCHAR* label; - - ASSERT(kdata); - ASSERT(attr); - - switch(attr->type) - { - /* - * The ID of the key. This should match the ID we - * return for any matching certificates. - */ - case CKA_ID: - return p11c_return_data(attr, kdata->key_identifier.pbData, - kdata->key_identifier.cbData); - - /* - * The key label. - * - We use the container name. - */ - case CKA_LABEL: - label = kdata->prov_info->pwszContainerName; - if(!label) - label = L"Unnamed Key"; - return p11c_return_string(attr, label); - - /* - * The subject of the related certificate. - * TODO: Implement this lookup. - */ - case CKA_SUBJECT: - return p11c_return_data(attr, "", 0); - - /* - * Allowed mechanisms with this key. - * - RSA used with CKM_RSA - * TODO: Needs updating when DSA implemented. - */ - case CKA_ALLOWED_MECHANISMS: - return p11c_return_data(attr, &allowed_mechanisms, - sizeof(allowed_mechanisms)); - - /* - * Various RSA public attributes. - */ - case CKA_MODULUS: - case CKA_PUBLIC_EXPONENT: - case CKA_PRIVATE_EXPONENT: - case CKA_PRIME_1: - case CKA_PRIME_2: - case CKA_EXPONENT_1: - case CKA_EXPONENT_2: - case CKA_COEFFICIENT: - if(kdata->prov_info->dwProvType == PROV_RSA_FULL) - return lookup_rsa_attribute(kdata, attr); - else - return CKR_ATTRIBUTE_TYPE_INVALID; - - /* - * Last date this key can be used. - * TODO: Does CAPI support this ability? - */ - case CKA_END_DATE: - case CKA_START_DATE: - return p11c_return_data(attr, "", 0); - - default: - return CKR_ATTRIBUTE_TYPE_INVALID; - }; -} - -static void -key_release(void* data) -{ - KeyObjectData* kdata = (KeyObjectData*)data; - ASSERT(kdata); - - ASSERT(kdata->key_identifier.pbData); - ASSERT(kdata->prov_info); - - free(kdata->key_identifier.pbData); - free(kdata->prov_info); - - free(kdata); -} - -static const P11cObjectDataVtable key_objdata_vtable = { - key_bool_attribute, - key_ulong_attribute, - key_bytes_attribute, - key_release, -}; - -static CRYPT_KEY_PROV_INFO* -duplicate_prov_info(CRYPT_KEY_PROV_INFO* original) -{ - DWORD container_length, prov_length; - CRYPT_KEY_PROV_INFO* result; - DWORD length, i; - BYTE* at; - BYTE* end; - - if(!original) - return NULL; - - /* Go through and calculate the length */ - length = sizeof(CRYPT_KEY_PROV_INFO); - if(original->pwszContainerName) - { - container_length = (wcslen(original->pwszContainerName) + 1) * sizeof(WCHAR); - length += container_length; - } - - if(original->pwszProvName) - { - prov_length = (wcslen(original->pwszProvName) + 1) * sizeof(WCHAR); - length += prov_length; - } - - length += sizeof(CRYPT_KEY_PROV_PARAM) * original->cProvParam; - for(i = 0; i < original->cProvParam; ++i) - length += original->rgProvParam[i].cbData; - - /* Allocate a single block of memory for everything */ - at = (BYTE*)malloc(length); - if(!at) - { - SetLastError(ERROR_NOT_ENOUGH_MEMORY); - return NULL; - } - - /* Copy in very carefully */ - end = at + length; - - memcpy(at, original, sizeof(CRYPT_KEY_PROV_INFO)); - result = (CRYPT_KEY_PROV_INFO*)at; - at += sizeof(CRYPT_KEY_PROV_INFO); - - if(result->pwszContainerName) - { - memcpy(at, result->pwszContainerName, container_length); - result->pwszContainerName = (LPWSTR)at; - at += container_length; - } - - if(result->pwszProvName) - { - memcpy(at, result->pwszProvName, prov_length); - result->pwszProvName = (LPWSTR)at; - at += prov_length; - } - - if(original->cProvParam) - { - memcpy(at, result->rgProvParam, sizeof(CRYPT_KEY_PROV_PARAM) * result->cProvParam); - result->rgProvParam = (CRYPT_KEY_PROV_PARAM*)at; - at += sizeof(CRYPT_KEY_PROV_PARAM) * result->cProvParam; - - for(i = 0; i < result->cProvParam; ++i) - { - memcpy(at, result->rgProvParam[i].pbData, result->rgProvParam[i].cbData); - result->rgProvParam[i].pbData = (BYTE*)at; - at += result->rgProvParam[i].cbData; - } - } - - ASSERT(at == end); - return result; -} - -static P11cObjectData* -key_alloc_data(P11cSession* sess, P11cObject* obj, CRYPT_KEY_PROV_INFO* prov_info) -{ - KeyObject* kobj = (KeyObject*)obj; - KeyObjectData* kdata; - - kdata = (KeyObjectData*)calloc(1, sizeof(KeyObjectData)); - if(!kdata) - return NULL; - - /* Allocate memory for key identifier */ - kdata->key_identifier.pbData = malloc(kobj->key_identifier.cbData); - if(!kdata->key_identifier.pbData) - { - free(kdata); - return NULL; - } - - /* Setup the object data */ - kdata->object_class = kobj->object_class; - kdata->prov_info = prov_info; - kdata->key_identifier.cbData = kobj->key_identifier.cbData; - memcpy(kdata->key_identifier.pbData, kobj->key_identifier.pbData, - kdata->key_identifier.cbData); - kdata->raw_public_key.pbData = NULL; - kdata->raw_public_key.cbData = 0; - - kdata->base.object = obj->id; - kdata->base.data_funcs = &key_objdata_vtable; - - return &(kdata->base); -} - -static BOOL WINAPI -load_key_property_info(PCRYPT_HASH_BLOB key_identifier, DWORD flags, - void* reserved, void* arg, DWORD n_props, DWORD* props, - void** datas, DWORD* n_datas) -{ - CRYPT_KEY_PROV_INFO** prov_info = (CRYPT_KEY_PROV_INFO**)arg; - DWORD i; - - /* - * Already got a provider info. This shouldn't happen - * but can occur if the same key is present twice. - */ - if(*prov_info) - return TRUE; - - /* Find the key provider info property */ - for(i = 0; i < n_props; ++i) - { - if(props[i] == CERT_KEY_PROV_INFO_PROP_ID) - { - *prov_info = duplicate_prov_info((CRYPT_KEY_PROV_INFO*)datas[i]); - break; - } - } - - return TRUE; -} - -static CK_RV -key_load_data(P11cSession* sess, P11cObject* obj, P11cObjectData** objdata) -{ - KeyObject* kobj = (KeyObject*)obj; - CRYPT_KEY_PROV_INFO* prov_info = NULL; - - ASSERT(kobj); - ASSERT(objdata); - - /* Load the provider info */ - if(!CryptEnumKeyIdentifierProperties((CRYPT_HASH_BLOB*)&kobj->key_identifier, - CERT_KEY_PROV_INFO_PROP_ID, 0, NULL, NULL, - &prov_info, load_key_property_info)) - return p11c_winerr_to_ckr(GetLastError()); - - /* No provider info, bad news */ - if(!prov_info) - return CKR_GENERAL_ERROR; - - *objdata = key_alloc_data(sess, obj, prov_info); - if(!(*objdata)) - { - free(prov_info); - return CKR_HOST_MEMORY; - } - - return CKR_OK; -} - -static unsigned int -key_hash_func(P11cObject* obj) -{ - KeyObject* kobj = (KeyObject*)obj; - return p11c_hash_data(kobj->key_identifier.pbData, kobj->key_identifier.cbData) ^ - p11c_hash_integer((int)kobj->object_class); -} - -static int -key_equal_func(P11cObject* a, P11cObject* b) -{ - KeyObject* ka = (KeyObject*)a; - KeyObject* kb = (KeyObject*)b; - return ka->object_class == kb->object_class && - ka->key_identifier.cbData == kb->key_identifier.cbData && - memcmp(ka->key_identifier.pbData, kb->key_identifier.pbData, ka->key_identifier.cbData) == 0; -} - -static void -key_object_release(void* data) -{ - KeyObject* kobj = (KeyObject*)data; - ASSERT(kobj); - free(kobj); -} - -static const P11cObjectVtable key_object_vtable = { - key_load_data, - key_hash_func, - key_equal_func, - key_object_release, -}; - -static CK_RV -register_key_object(P11cSession* sess, CK_OBJECT_CLASS cls, - CRYPT_HASH_BLOB* key_identifier, P11cObject** obj) -{ - KeyObject* kobj; - CK_RV ret; - - ASSERT(obj); - ASSERT(key_identifier); - ASSERT(cls == CKO_PRIVATE_KEY || cls == CKO_PUBLIC_KEY); - - kobj = calloc(1, sizeof(KeyObject) + key_identifier->cbData); - if(!kobj) - return CKR_HOST_MEMORY; - - kobj->obj.id = 0; - kobj->obj.obj_funcs = &key_object_vtable; - - kobj->object_class = cls; - kobj->key_identifier.pbData = (BYTE*)(kobj + 1); - kobj->key_identifier.cbData = key_identifier->cbData; - memcpy(kobj->key_identifier.pbData, key_identifier->pbData, - kobj->key_identifier.cbData); - - ret = p11c_token_register_object(sess->slot, &(kobj->obj)); - if(ret != CKR_OK) - { - free(kobj); - return ret; - } - - ASSERT(kobj->obj.id != 0); - *obj = &(kobj->obj); - - return CKR_OK; -} - -typedef struct _EnumArguments -{ - P11cSession* sess; - CK_OBJECT_CLASS object_class; - CK_ATTRIBUTE_PTR match; - CK_ULONG count; - P11cArray* results; - CK_RV ret; -} -EnumArguments; - -static BOOL WINAPI -enum_key_property_info(PCRYPT_HASH_BLOB key_identifier, DWORD flags, - void* reserved, void* arg, DWORD n_props, DWORD* props, - void** datas, DWORD* n_datas) -{ - EnumArguments* args = (EnumArguments*)arg; - CRYPT_KEY_PROV_INFO* prov_info = NULL; - P11cObject *obj = NULL; - KeyObjectData kdata; - DWORD i; - - /* Find the key provider info property */ - for(i = 0; i < n_props; ++i) - { - if(props[i] == CERT_KEY_PROV_INFO_PROP_ID) - { - prov_info = (CRYPT_KEY_PROV_INFO*)datas[i]; - break; - } - } - - /* Strange key, skip */ - if(!prov_info) - return TRUE; - - /* Match the public key */ - kdata.prov_info = prov_info; - kdata.object_class = args->object_class; - kdata.base.object = 0; - kdata.base.data_funcs = &key_objdata_vtable; - - if(p11c_object_data_match(&kdata.base, args->match, args->count)) - { - args->ret = register_key_object(args->sess, args->object_class, key_identifier, &obj); - if(args->ret == CKR_OK) - { - ASSERT(obj); - p11c_array_append(args->results, obj->id); - } - } - - return TRUE; - -} - -static CK_RV -find_any_keys(P11cSession* sess, CK_OBJECT_CLASS cls, - CK_ATTRIBUTE_PTR match, CK_ULONG count, P11cArray* arr) -{ - CRYPT_HASH_BLOB find_id; - EnumArguments enum_args; - CK_ULONG i; - - /* Try to setup for an efficient search based on key id */ - memset(&find_id, 0, sizeof(find_id)); - for(i = 0; i < count; ++i) - { - if(!match[i].pValue || !match[i].ulValueLen) - continue; - if(match[i].type == CKA_ID) - { - find_id.cbData = match[i].ulValueLen; - find_id.pbData = match[i].pValue; - } - } - - enum_args.sess = sess; - enum_args.match = match; - enum_args.count = count; - enum_args.results = arr; - enum_args.object_class = cls; - enum_args.ret = CKR_OK; - - if(!CryptEnumKeyIdentifierProperties(find_id.cbData != 0 ? &find_id : NULL, - CERT_KEY_PROV_INFO_PROP_ID, 0, NULL, NULL, - &enum_args, enum_key_property_info)) - return p11c_winerr_to_ckr(GetLastError()); - - return enum_args.ret; -} - -static CK_RV -list_matching_certificates(P11cSession* sess, CK_ATTRIBUTE_PTR match, - CK_ULONG count, P11cArray* arr) -{ - CK_OBJECT_CLASS cert_class = CKO_CERTIFICATE; - CK_ATTRIBUTE search[3]; - CK_ULONG n_search = 0; - CK_ULONG i; - - /* The class */ - search[0].type = CKA_CLASS; - search[0].pValue = &cert_class; - search[0].ulValueLen = sizeof(CK_OBJECT_CLASS); - ++n_search; - - for(i = 0; i < count && n_search < 3; ++i) - { - /* - * This is the attributes that tie a certificate - * to key object, so try match certs with these - */ - if(match[i].type == CKA_ID) - { - search[n_search].type = match[i].type; - search[n_search].pValue = match[i].pValue; - search[n_search].ulValueLen = match[i].ulValueLen; - ++n_search; - } - } - - /* Do the certificate search */ - return p11c_cert_find(sess, CKO_CERTIFICATE, search, n_search, arr); -} - -static CK_RV -find_certificate_key(P11cSession* session, CK_OBJECT_CLASS cls, - CK_ATTRIBUTE_PTR match, CK_ULONG count, - PCCERT_CONTEXT cert, P11cArray* arr) -{ - CRYPT_KEY_PROV_INFO* prov_info; - CRYPT_HASH_BLOB key_identifier; - P11cObjectData* objdata; - KeyObjectData kdata; - P11cObject* obj; - DWORD prov_length; - DWORD error; - CK_RV ret = CKR_OK; - - /* Look up the key provider info and identifier */ - if(!CertGetCertificateContextProperty(cert, CERT_KEY_PROV_INFO_PROP_ID, NULL, &prov_length) || - !CertGetCertificateContextProperty(cert, CERT_KEY_IDENTIFIER_PROP_ID, NULL, &key_identifier.cbData)) - { - error = GetLastError(); - if(error == CRYPT_E_NOT_FOUND) - return CKR_OK; - return p11c_winerr_to_ckr(error); - } - - /* We own the info memory */ - prov_info = malloc(prov_length); - if(!prov_info) - return CKR_HOST_MEMORY; - key_identifier.pbData = malloc(key_identifier.cbData); - if(!key_identifier.pbData) - { - free(prov_info); - return CKR_HOST_MEMORY; - } - - /* Lookup the key provider info and identifier */ - if(CertGetCertificateContextProperty(cert, CERT_KEY_PROV_INFO_PROP_ID, prov_info, &prov_length) && - CertGetCertificateContextProperty(cert, CERT_KEY_IDENTIFIER_PROP_ID, key_identifier.pbData, &key_identifier.cbData)) - { - kdata.object_class = cls; - kdata.prov_info = prov_info; - kdata.key_identifier = key_identifier; - kdata.base.object = 0; - kdata.base.data_funcs = &key_objdata_vtable; - - if(p11c_object_data_match(&kdata.base, match, count)) - { - ret = register_key_object(session, cls, &key_identifier, &obj); - if(ret == CKR_OK) - { - ASSERT(obj); - - /* Store away the object data for performance reasons */ - objdata = key_alloc_data(session, obj, prov_info); - if(objdata) - { - p11c_session_take_object_data(session, obj, objdata); - - /* Note these are used, and not to be freed */ - key_identifier.pbData = NULL; - key_identifier.cbData = 0; - prov_info = NULL; - } - - p11c_array_append(arr, obj->id); - } - } - } - else - { - ret = p11c_winerr_to_ckr(GetLastError()); - } - - if(key_identifier.pbData) - free(key_identifier.pbData); - if(prov_info) - free(prov_info); - - return ret; -} - -static CK_RV -find_certificate_keys(P11cSession* session, CK_OBJECT_CLASS cls, - CK_ATTRIBUTE_PTR match, CK_ULONG count, P11cArray* arr) -{ - CK_OBJECT_HANDLE id; - P11cObjectData* certdata; - P11cArray* certarr; - PCCERT_CONTEXT cert; - CK_RV ret = CKR_OK; - CK_ULONG i; - - /* Get a list of all certificates */ - certarr = p11c_array_new(0, 1, sizeof(CK_OBJECT_HANDLE)); - if(!certarr) - return CKR_HOST_MEMORY; - ret = list_matching_certificates(session, match, count, certarr); - - /* Now match each of them against our criteria */ - if(ret == CKR_OK) - { - for(i = 0; i < certarr->len; ++i) - { - id = p11c_array_index(certarr, CK_OBJECT_HANDLE, i); - ASSERT(id); - - /* Get the certificate data for this certificate object */ - if(p11c_session_get_object_data_for(session, id, &certdata) != CKR_OK) - continue; - - /* Get the certificate context */ - cert = p11c_cert_object_data_get_certificate(certdata); - if(!cert) - continue; - - /* Remember we can have either or both keys for each certificate */ - ret = find_certificate_key(session, cls, match, count, cert, arr); - } - } - - p11c_array_free(certarr, TRUE); - return ret; -} - -CK_RV -p11c_key_find(P11cSession* sess, CK_OBJECT_CLASS cls, - CK_ATTRIBUTE_PTR match, CK_ULONG count, P11cArray* arr) -{ - CK_RV ret = CKR_OK; - - /* Is this somewhere we have all keys present? */ - if(p11c_token_get_flags(sess->slot) & P11C_SLOT_ANYKEY) - { - if((cls == CKO_PRIVATE_KEY || cls == CKO_ANY) && ret == CKR_OK) - ret = find_any_keys(sess, CKO_PRIVATE_KEY, match, count, arr); - if((cls == CKO_PUBLIC_KEY || cls == CKO_ANY) && ret == CKR_OK) - ret = find_any_keys(sess, CKO_PUBLIC_KEY, match, count, arr); - } - - /* Otherwise we can only list the keys that have certificates */ - else - { - if((cls == CKO_PRIVATE_KEY || cls == CKO_ANY) && ret == CKR_OK) - ret = find_certificate_keys(sess, CKO_PRIVATE_KEY, match, count, arr); - if((cls == CKO_PUBLIC_KEY || cls == CKO_ANY) && ret == CKR_OK) - ret = find_certificate_keys(sess, CKO_PUBLIC_KEY, match, count, arr); - } - - return ret; -} - -DWORD -p11c_key_object_data_get_bits(P11cObjectData* objdata) -{ - KeyObjectData* kdata; - PUBLICKEYSTRUC* header; - RSAPUBKEY* pubkey; - CK_RV ret; - - ASSERT(objdata); - - kdata = (KeyObjectData*)objdata; - - if(!kdata->raw_public_key.pbData) - { - ret = load_raw_public_key(kdata); - if(ret != CKR_OK) - return ret; - } - - header = (PUBLICKEYSTRUC*)kdata->raw_public_key.pbData; - if(!header->bType == PUBLICKEYBLOB) - return 0; - - pubkey = (RSAPUBKEY*)(header + 1); - if(!pubkey->magic == 0x31415352) - return 0; - - return pubkey->bitlen; -} - -CRYPT_KEY_PROV_INFO* -p11c_key_object_data_get_prov_info(P11cObjectData* objdata) -{ - KeyObjectData* kdata; - - ASSERT(objdata); - kdata = (KeyObjectData*)objdata; - return kdata->prov_info; -} |