diff options
| author | Stef Walter <stef@memberwebs.com> | 2008-12-04 18:59:50 +0000 | 
|---|---|---|
| committer | Stef Walter <stef@memberwebs.com> | 2008-12-04 18:59:50 +0000 | 
| commit | d611032e1e5b4e2261625ee924071e9713320837 (patch) | |
| tree | 66683785a16c02975b675017f460eb9ed14e799d | |
| parent | b00eb56b7ffe5019bb33ad399d351b90f4715132 (diff) | |
Implement RSA Sign and Decrypt operations. Not tested.
| -rw-r--r-- | ckcapi-der.c | 177 | ||||
| -rw-r--r-- | ckcapi-der.h | 35 | ||||
| -rw-r--r-- | ckcapi-key.c | 92 | ||||
| -rw-r--r-- | ckcapi-key.h | 11 | ||||
| -rw-r--r-- | ckcapi-rsa.c | 405 | ||||
| -rw-r--r-- | ckcapi-rsa.h | 41 | ||||
| -rw-r--r-- | ckcapi-session.c | 199 | ||||
| -rw-r--r-- | ckcapi-session.h | 27 | ||||
| -rw-r--r-- | ckcapi.c | 128 | ||||
| -rw-r--r-- | ckcapi.h | 5 | ||||
| -rw-r--r-- | ckcapi.vcproj | 16 | 
11 files changed, 1063 insertions, 73 deletions
diff --git a/ckcapi-der.c b/ckcapi-der.c new file mode 100644 index 0000000..602b831 --- /dev/null +++ b/ckcapi-der.c @@ -0,0 +1,177 @@ +/*  + * Portions derived from NSS source files:  + *     lib/ckfw/capi/cobject.c + *     lib/ckfw/capi/crsa.c + * + * Portions of this file: + *     Copyright (C) Stef Walter 2008 + *  + */ + +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is the Netscape security libraries. + * + * The Initial Developer of the Original Code is + * Netscape Communications Corporation. + * Portions created by the Initial Developer are Copyright (C) 1994-2000 + * the Initial Developer. All Rights Reserved. + * Portions created by Red Hat, Inc, are Copyright (C) 2005 + * + * Contributor(s): + *   Bob Relyea (rrelyea@redhat.com) + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#include "ckcapi.h" +#include "ckcapi-der.h" + +/* + * unwrap a single DER value + */ +BYTE* +ckcapi_der_unwrap(BYTE* src, DWORD n_src,  +                  DWORD* n_result, BYTE** next) +{ +	BYTE* start = src; +	BYTE* end = src + n_src; +	DWORD len = 0; + +	/* initialize error condition return values */ +	*n_result = 0; +	if(next) +		*next = src; + +	if(n_src < 2) +		return start; + +	src++ ; /* skip the tag -- should check it against an expected value! */ +	len = (DWORD)*src++; +	if(len & 0x80)  +	{ +		DWORD count = len & 0x7f; +		len = 0; + +		if(count + 2 > n_src)  +			return start; + +		while(count-- > 0) +			len = (len << 8) | (DWORD)*src++; +	} + +	if(len + (src - start) > (DWORD)n_src) +		return start; + +	if(next) +		*next = src + len; + +	*n_result = len; +	return src; +} + +/* + * write a Decimal value to a string + */ + +static char* +put_decimal_string(char* cstr, DWORD value) +{ +	DWORD tenpower; +	BOOL first = TRUE; + +	for(tenpower = 10000000; tenpower; tenpower /= 10)  +	{ +		BYTE digit = (BYTE)(value / tenpower); +		value = value % tenpower; + +		/* drop leading zeros */ +		if(first && (0 == digit)) +			continue; + +		first = FALSE; +		*cstr++ = digit + '0'; +	} + +	/* if value was zero, put one of them out */ +	if(first) +		*cstr++ = '0'; + +	return cstr; +} + +/* + * Create a Capi OID string value from a DER OID + */ +char* +ckcapi_der_read_oid(BYTE* oid_tag, DWORD n_oid_tag) +{ +	BYTE* oid; +	char *oid_str; +	char *cstr; +	DWORD value; +	DWORD n_oid; + +	/* wasn't an oid */ +	if(CKCAPI_DER_OBJECT_ID != *oid_tag)  +		return NULL; + +	oid = ckcapi_der_unwrap(oid_tag, n_oid_tag, &n_oid, NULL);; +	if(n_oid < 2)  +		return NULL; + +	oid_str = malloc(n_oid * 4); +	if(!oid_str)  +		return NULL; + +	cstr = oid_str; +	cstr = put_decimal_string(cstr, (*oid) / 40); +	*cstr++ = '.'; +	cstr = put_decimal_string(cstr, (*oid) % 40); +	n_oid--; + +	value = 0; +	while(n_oid--)  +	{ +		oid++; +		value = (value << 7) + (*oid & 0x7f); +		if(0 == (*oid & 0x80))  +		{ +			*cstr++ = '.'; +			cstr = put_decimal_string(cstr, value); +			value = 0; +		} +	} + +	*cstr = 0; /* NULL terminate */ + +	if(value != 0)  +	{ +		free(oid_str); +		return NULL; +	} + +	return oid_str; +} diff --git a/ckcapi-der.h b/ckcapi-der.h new file mode 100644 index 0000000..9030ce3 --- /dev/null +++ b/ckcapi-der.h @@ -0,0 +1,35 @@ +/*  + * 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. + */ + +#ifndef CKCAPI_DER_H +#define CKCAPI_DER_H + +#include "ckcapi.h" + +#define CKCAPI_DER_OCTET_STRING        0x04 +#define CKCAPI_DER_OBJECT_ID           0x06 +#define CKCAPI_DER_SEQUENCE            0x10 +#define CKCAPI_DER_CONSTRUCTED         0x20 + +BYTE*    ckcapi_der_unwrap      (BYTE* src, DWORD n_src,  +                                 DWORD* n_result, BYTE** next); + +char*    ckcapi_der_read_oid    (BYTE* oid_tag, DWORD n_oid_tag); + +#endif /* CRYPTOKI_DER_H */ diff --git a/ckcapi-key.c b/ckcapi-key.c index 1ce057c..88e769e 100644 --- a/ckcapi-key.c +++ b/ckcapi-key.c @@ -98,6 +98,40 @@ typedef struct _KeyObjectData  KeyObjectData;  static CK_RV +load_key_handle (CkCapiObjectData* objdata, HCRYPTKEY* ret_key) +{ +	KeyObjectData* kdata = (KeyObjectData*)objdata; +	HCRYPTPROV prov; +	HCRYPTKEY key; +	DWORD error; + +	ASSERT(kdata); + +	if(!CryptAcquireContextW(&prov, kdata->prov_info->pwszContainerName,  +	                         kdata->prov_info->pwszProvName,  +	                         kdata->prov_info->dwProvType, 0)) +	{ +		return ckcapi_winerr_to_ckr(GetLastError()); +	} + +	if(!CryptGetUserKey(prov, kdata->prov_info->dwKeySpec, &key)) +	{ +		error = GetLastError(); +		CryptReleaseContext(prov, 0); +		return ckcapi_winerr_to_ckr(error); +	} + +	if(ret_key) +		*ret_key = key; +	else +		CryptDestroyKey(key); + +	CryptReleaseContext(prov, 0); +	return CKR_OK; +} + + +static CK_RV  load_raw_public_key(KeyObjectData* kdata)  {  	BOOL success = FALSE; @@ -108,7 +142,7 @@ load_raw_public_key(KeyObjectData* kdata)  	ASSERT(kdata);  	ASSERT(!kdata->raw_public_key.pbData); -	ret = ckcapi_key_object_data_get_handles(&kdata->base, NULL, &key); +	ret = load_key_handle(&kdata->base, &key);  	if(ret != CKR_OK)  		return ret; @@ -994,40 +1028,42 @@ ckcapi_key_find(CkCapiSession* sess, CK_OBJECT_CLASS cls,  	return ret;  } -CK_RV -ckcapi_key_object_data_get_handles (CkCapiObjectData* objdata, HCRYPTPROV* ret_prov, -                                    HCRYPTKEY* ret_key) +DWORD +ckcapi_key_object_data_get_bits(CkCapiObjectData* objdata)  { -	KeyObjectData* kdata = (KeyObjectData*)objdata; -	HCRYPTPROV prov; -	HCRYPTKEY key; -	DWORD error; +	KeyObjectData* kdata; +	PUBLICKEYSTRUC* header; +	RSAPUBKEY* pubkey; +	CK_RV ret; -	ASSERT(kdata); +	ASSERT(objdata); -	if(!CryptAcquireContextW(&prov, kdata->prov_info->pwszContainerName,  -	                         kdata->prov_info->pwszProvName,  -	                         kdata->prov_info->dwProvType, 0)) +	kdata = (KeyObjectData*)objdata; +	 +	if(!kdata->raw_public_key.pbData)  	{ -		return ckcapi_winerr_to_ckr(GetLastError()); +		ret = load_raw_public_key(kdata); +		if(ret != CKR_OK) +			return ret;  	} -	if(!CryptGetUserKey(prov, kdata->prov_info->dwKeySpec, &key)) -	{ -		error = GetLastError(); -		CryptReleaseContext(prov, 0); -		return ckcapi_winerr_to_ckr(error); -	} +	header = (PUBLICKEYSTRUC*)kdata->raw_public_key.pbData; +	if(!header->bType == PUBLICKEYBLOB) +		return 0; -	if(ret_key) -		*ret_key = key; -	else -		CryptDestroyKey(key); +	pubkey = (RSAPUBKEY*)(header + 1); +	if(!pubkey->magic == 0x31415352) +		return 0; -	if(ret_prov) -		*ret_prov = prov; -	else -		CryptReleaseContext(prov, 0); +	return pubkey->bitlen; +} -	return CKR_OK; +CRYPT_KEY_PROV_INFO* +ckcapi_key_object_data_get_prov_info(CkCapiObjectData* objdata) +{ +	KeyObjectData* kdata; + +	ASSERT(objdata); +	kdata = (KeyObjectData*)objdata; +	return kdata->prov_info;  } diff --git a/ckcapi-key.h b/ckcapi-key.h index d09b30c..eabe7a9 100644 --- a/ckcapi-key.h +++ b/ckcapi-key.h @@ -23,11 +23,12 @@  #include "ckcapi.h"  /* Find key objects matching criteria */ -CK_RV				ckcapi_key_find		    			(CkCapiSession* sess, CK_OBJECT_CLASS cls,  -											    		 CK_ATTRIBUTE_PTR match, CK_ULONG count,  -												    	 CkCapiArray* arr); +CK_RV                ckcapi_key_find                      (CkCapiSession* sess, CK_OBJECT_CLASS cls,  +                                                           CK_ATTRIBUTE_PTR match, CK_ULONG count,  +                                                           CkCapiArray* arr); -CK_RV               ckcapi_key_object_data_get_handles  (CkCapiObjectData* objdata, HCRYPTPROV* prov, -                                                         HCRYPTKEY* key); +DWORD                ckcapi_key_object_data_get_bits      (CkCapiObjectData* objdata); + +CRYPT_KEY_PROV_INFO* ckcapi_key_object_data_get_prov_info (CkCapiObjectData* objdata);  #endif /* CRYPTOKI_KEY_H */ diff --git a/ckcapi-rsa.c b/ckcapi-rsa.c new file mode 100644 index 0000000..0d4e75d --- /dev/null +++ b/ckcapi-rsa.c @@ -0,0 +1,405 @@ +/*  + * 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 "ckcapi.h" + +#include "ckcapi-der.h" +#include "ckcapi-key.h" +#include "ckcapi-object.h" + +/*  + * Portions derived from NSS source files:  + *     lib/ckfw/capi/crsa.c + */ + +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is the Netscape security libraries. + * + * The Initial Developer of the Original Code is + * Red Hat, Inc. + * Portions created by the Initial Developer are Copyright (C) 2005 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + *   Bob Relyea (rrelyea@redhat.com) + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#define SSL3_SHAMD5_HASH_SIZE  36 /* LEN_MD5 (16) + LEN_SHA1 (20) */ + +/* + * PKCS #11 sign for RSA expects to take a fully DER-encoded hash value,  + * which includes the hash OID. CAPI expects to take a Hash Context. While  + * CAPI does have the capability of setting a raw hash value, it does not  + * have the ability to sign an arbitrary value. This function tries to + * reduce the passed in data into something that CAPI could actually sign. + */ +static CK_BYTE_PTR +parse_rsa_pkcs_der_hash(CK_BYTE_PTR input, CK_ULONG n_input, +                        ALG_ID* algorithm, CK_ULONG_PTR n_hash) +{ +	BYTE* algid; +	BYTE* oid; +	BYTE* hash_data; +	BYTE* oid_str; +	DWORD n_oid; +	DWORD n_algid; + +	/* +	 * there are 2 types of hashes NSS typically tries to sign, regular +	 * RSA signature format (with encoded DER_OIDS), and SSL3 Signed hashes. +	 * CAPI knows not to add any oids to SSL3_Signed hashes, so if we have any +	 * random hash that is exactly the same size as an SSL3 hash, then we can +	 * just pass the data through. CAPI has know way of knowing if the value +	 * is really a combined hash or some other arbitrary data, so it's safe to +	 * handle this case first. +	 */ +	if(SSL3_SHAMD5_HASH_SIZE == n_input) +	{ +		*n_hash = n_input; +		*algorithm = CALG_SSL3_SHAMD5; +		return input; +	} + +	/* make sure we have a sequence tag */ +	if((CKCAPI_DER_SEQUENCE | CKCAPI_DER_CONSTRUCTED) != *input) +		return NULL; + +	/*  +	 * parse the input block to get 1) the hash oid, and 2) the raw hash value. +	 * unfortunatly CAPI doesn't have a builtin function to do this work, so +	 * we go ahead and do it by hand here. +	 * +	 * format is: +	 *  SEQUENCE { +	 *     SECQUENCE { // algid +	 *       OID {}    // oid +	 *       ANY {}    // optional params  +	 *     } +	 *     OCTECT {}   // hash +	 */ + +	/* unwrap */ +	algid = ckcapi_der_unwrap(input, n_input, &n_algid, NULL); +	if(!algid) +		return NULL; +	 +	/* make sure there is not extra data at the end */ +	if(algid + n_algid != input + n_input) +		return NULL; + +	/* wasn't an algid */ +	if((CKCAPI_DER_SEQUENCE | CKCAPI_DER_CONSTRUCTED) != *algid) +		return NULL; + +	oid = ckcapi_der_unwrap(algid, n_algid, &n_oid, &hash_data); +	if(!oid || !hash_data) +		return NULL; + +	if(algorithm) +	{ +		/*  +		 * get the real oid as a string. Again, Microsoft does not +		 * export anything that does this for us  +		 */ +		oid_str = ckcapi_der_read_oid(oid, n_oid); +		if(!oid_str) +			return NULL; + +		/* look up the hash alg from the oid (fortunately CAPI does to this) */  +		*algorithm = CertOIDToAlgId(oid_str); +		free(oid_str); +	} + +	/* wasn't a hash? */ +	if(CKCAPI_DER_OCTET_STRING != *hash_data) +		return NULL; + +	/* get the real raw hash */ +	return ckcapi_der_unwrap(hash_data, n_algid - (hash_data - algid),  +	                         n_hash, NULL); +} + +CK_RV +ckcapi_rsa_pkcs_sign_init(CkCapiObjectData *keydata, void** operation) +{ +	CRYPT_KEY_PROV_INFO* prov_info; + +	ASSERT(keydata); +	ASSERT(operation); +	ASSERT(!*operation); +	 +	prov_info = ckcapi_key_object_data_get_prov_info(keydata); +	if(prov_info->dwProvType == PROV_RSA_FULL) +		return CKR_KEY_TYPE_INCONSISTENT; + +	*operation = keydata; +	return CKR_OK; +} + +CK_RV +ckcapi_rsa_pkcs_sign_perform (CK_BYTE_PTR data, CK_ULONG n_data, +                              CK_BYTE_PTR signature, CK_ULONG_PTR n_signature, +                              void** operation) +{ +	CRYPT_KEY_PROV_INFO* prov_info; +	CkCapiObjectData* keydata; +	ALG_ID algorithm; +	BYTE* hash_data; +	DWORD n_hash_data; +	BOOL capifail; +	DWORD len, check; +	DWORD bits; +	CK_RV ret; + +	HCRYPTPROV prov = 0; +	HCRYPTHASH hash = 0; + + +	ASSERT(operation); +	ASSERT(*operation); + +	if(!data || !n_data) +		return CKR_ARGUMENTS_BAD; + +	keydata = (CkCapiObjectData*)*operation; + +	prov_info = ckcapi_key_object_data_get_prov_info(keydata); +	ASSERT(prov_info); + +	/* Calculate the number of bits */ +	bits = ckcapi_key_object_data_get_bits (keydata); +	if(!bits) +		return CKR_GENERAL_ERROR; + +	/* Want to know the length */ +	if(!signature)  +	{ +		*n_signature = bits / 8; +		return CKR_OK; +	} + +	/* TODO: Support arbitrary input on Vista */ + +	/* +	 * PKCS #11 sign for RSA expects to take a fully DER-encoded hash value,  +	 * which includes the hash OID. CAPI expects to take a Hash Context. While  +	 * CAPI does have the capability of setting a raw hash value, it does not  +	 * have the ability to sign an arbitrary value. This function tries to +	 * reduce the passed in data into something that CAPI could actually sign. +	 */ +	hash_data = parse_rsa_pkcs_der_hash(data, n_data, &algorithm, &n_hash_data); +	if(!hash_data) +		return CKR_DATA_INVALID; + +	capifail = TRUE; +	if(CryptAcquireContextW(&prov, prov_info->pwszContainerName, prov_info->pwszProvName, +	                        prov_info->dwProvType, 0)) +	{ +		if(CryptCreateHash(prov, algorithm, 0, 0, &hash)) +		{ +			/* make sure the hash lens match before we set it */ +			len = sizeof(DWORD); +			if(CryptGetHashParam(hash, HP_HASHSIZE, (BYTE*)&check, &len, 0)) +			{ +				if(check != n_hash_data)  +				{ +					capifail = FALSE; +					ret = CKR_DATA_INVALID; +				} + +				/*  +				 * we have an explicit hash, set it, note that the length is +		 		 * implicit by the hashAlg used in create  +				 */ +				if(CryptSetHashParam(hash, HP_HASHVAL, hash_data, 0)) +				{ +					/* OK, we have the data in a hash structure, sign it! */ +					if(CryptSignHash(hash, prov_info->dwKeySpec,  +					                 NULL, 0, signature, n_signature)) +					{ +						/*  +						 * OK, Microsoft likes to do things completely  +						 * differently than anyone else. We need to reverse  +						 * the data we recieved here  +						 */ +						if(signature) +							ckcapi_reverse_memory(signature, *n_signature); +	 +						capifail = FALSE; +						ret = CKR_OK; +					} +				} +			} +		} +	} + +	if(capifail) +		ret = ckcapi_winerr_to_ckr(GetLastError()); + +	if(hash) +		CryptDestroyHash(hash); +	if(prov) +		CryptReleaseContext(prov, 0); + +	return ret; +} + +void +ckcapi_rsa_pkcs_sign_cleanup (void* operation) +{ +	/* Nothing to do */ +} + + +CK_RV +ckcapi_rsa_pkcs_decrypt_init(CkCapiObjectData* keydata, void** operation) +{ +	CRYPT_KEY_PROV_INFO* prov_info; + +	ASSERT(keydata); +	ASSERT(operation); +	ASSERT(!*operation); +	 +	prov_info = ckcapi_key_object_data_get_prov_info(keydata); +	if(prov_info->dwProvType == PROV_RSA_FULL) +		return CKR_KEY_TYPE_INCONSISTENT; + +	*operation = keydata; +	return CKR_OK; +} + +CK_RV +ckcapi_rsa_pkcs_decrypt_perform(CK_BYTE_PTR encdata, CK_ULONG n_encdata, +                                CK_BYTE_PTR result, CK_ULONG_PTR n_result, +                                void** operation) +{ +	CRYPT_KEY_PROV_INFO* prov_info; +	CkCapiObjectData* keydata; +	BOOL capifail; +	DWORD bits, error; +	CK_RV ret; + +	HCRYPTPROV prov = 0; +	HCRYPTKEY key = 0; +	void* buffer = NULL; + +	ASSERT(operation); +	ASSERT(*operation); +	ASSERT(encdata); +	ASSERT(n_encdata); + +	keydata = (CkCapiObjectData*)*operation; + +	prov_info = ckcapi_key_object_data_get_prov_info(keydata); +	ASSERT(prov_info); + +	/* Calculate the number of bits */ +	bits = ckcapi_key_object_data_get_bits (keydata); +	if(!bits) +		return CKR_GENERAL_ERROR; + +	/* Want to know the length */ +	if(!result)  +	{ +		*n_result = bits / 8; +		return CKR_OK; +	} + +	/*  +	 * Copy the input, since CAPI operates in place, and  +	 * we must also reverse it properly. +	 */ +	buffer = malloc(n_encdata); +	if(!buffer) +		return CKR_HOST_MEMORY; + +	memcpy(buffer, encdata, n_encdata); +	ckcapi_reverse_memory(buffer, n_encdata); + +	capifail = TRUE; +	if(CryptAcquireContextW(&prov, prov_info->pwszContainerName, prov_info->pwszProvName, +	                        prov_info->dwProvType, 0)) +	{ +		if(CryptGetUserKey(prov, prov_info->dwKeySpec, &key)) +		{ +			*n_result = n_encdata; +			if(CryptDecrypt(key, 0, TRUE, 0, buffer, n_result)) +			{ +				capifail = FALSE; +				ret = CKR_OK; +			} +		} +	} + +	if(capifail) +	{ +		error = GetLastError(); +		switch(error) +		{ +		case NTE_BAD_DATA: +			ret = CKR_ENCRYPTED_DATA_INVALID; +		default: +			ret = ckcapi_winerr_to_ckr(error); +		}; +	} + +	/* Copy the memory out to the result buffer */ +	if(ret == CKR_OK) +		ret = ckcapi_return_data_raw(result, n_result, buffer, *n_result); + +	if(key) +		CryptDestroyKey(key); +	if(prov) +		CryptReleaseContext(prov, 0); +	if(buffer) +		free(buffer); + +	return ret; +} + +void +ckcapi_rsa_pkcs_decrypt_cleanup(void* operation) +{ +	/* Nothing to do */ +} diff --git a/ckcapi-rsa.h b/ckcapi-rsa.h new file mode 100644 index 0000000..4e00133 --- /dev/null +++ b/ckcapi-rsa.h @@ -0,0 +1,41 @@ +/*  + * 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. + */ + +#ifndef CKCAPI_RSA_H +#define CKCAPI_RSA_H + +#include "ckcapi.h" + +CK_RV      ckcapi_rsa_pkcs_sign_init        (CkCapiObjectData* keydata, void** operation); + +CK_RV      ckcapi_rsa_pkcs_sign_perform     (CK_BYTE_PTR data, CK_ULONG data_len, +                                             CK_BYTE_PTR signature, CK_ULONG_PTR signature_len, +										     void** operation); + +void       ckcapi_rsa_pkcs_sign_cleanup     (void* operation); + +CK_RV      ckcapi_rsa_pkcs_decrypt_init     (CkCapiObjectData* keydata, void** operation); + +CK_RV      ckcapi_rsa_pkcs_decrypt_perform  (CK_BYTE_PTR encdata, CK_ULONG n_encdata, +                                             CK_BYTE_PTR result, CK_ULONG_PTR n_result, +										     void** operation); + +void       ckcapi_rsa_pkcs_decrypt_cleanup  (void* operation); + +#endif /* CKCAPI_RSA_H */ diff --git a/ckcapi-session.c b/ckcapi-session.c index 46de60a..0745cb7 100644 --- a/ckcapi-session.c +++ b/ckcapi-session.c @@ -23,10 +23,20 @@  #include "ckcapi-builtin.h"  #include "ckcapi-cert.h"  #include "ckcapi-object.h" +#include "ckcapi-rsa.h"  #include "ckcapi-session.h"  #include "ckcapi-token.h"  #include "ckcapi-trust.h" +/* For operation_type in CkCapiSession */ +enum +{ +	OPERATION_NONE, +	OPERATION_FIND, +	OPERATION_SIGN, +	OPERATION_DECRYPT +}; +  static CkCapiArray* all_sessions = NULL;  static void @@ -721,3 +731,192 @@ ckcapi_session_find_final(CkCapiSession* sess)  } +/* ---------------------------------------------------------------------------- + * CRYPTO OPERATIONS + */ + +typedef struct _CryptoContext  +{ +	CK_MECHANISM_TYPE mech_type; +	CkCapiDestroyFunc mech_cleanup; +	void* mech_data; +} +CryptoContext; + +void  +cleanup_crypto_operation(CkCapiSession* sess) +{ +	CryptoContext* ctx; + +	if(sess->operation_data) +	{ +		ctx = (CryptoContext*)sess->operation_data; +		if(ctx->mech_cleanup) +			(ctx->mech_cleanup)(ctx->mech_data); +		free(ctx); +	} + +	sess->operation_type = OPERATION_NONE; +	sess->operation_data = NULL; +	sess->operation_cancel = NULL; +} + +CK_RV +ckcapi_session_sign_init(CkCapiSession* sess, CK_MECHANISM_PTR mech,  +						 CkCapiObjectData *objdata) +{ +	CryptoContext* ctx; +	CK_RV ret; + +	ASSERT(sess); +	ASSERT(mech); +	ASSERT(objdata); + +	if(sess->operation_type != OPERATION_NONE) +		return CKR_OPERATION_ACTIVE; + +	ctx = calloc(1, sizeof(CryptoContext)); +	if(!ctx) +		return CKR_HOST_MEMORY; + +	ctx->mech_type = mech->mechanism; + +	switch(mech->mechanism) +	{ +	case CKM_RSA_PKCS: +		ret = ckcapi_rsa_pkcs_sign_init(objdata, &ctx->mech_data); +		ctx->mech_cleanup = ckcapi_rsa_pkcs_sign_cleanup; +	default: +		ret = CKR_MECHANISM_INVALID; +	}; + +	if(ret != CKR_OK) +	{ +		free(ctx); +		ASSERT(!sess->operation_data); +		return ret; +	} + +	sess->operation_type = OPERATION_SIGN; +	sess->operation_data = ctx; +	sess->operation_cancel = cleanup_crypto_operation; +	return CKR_OK; +} + +CK_RV +ckcapi_session_sign(CkCapiSession* sess, CK_BYTE_PTR data, CK_ULONG n_data, +                    CK_BYTE_PTR signature, CK_ULONG_PTR n_signature) +{ +	CryptoContext *ctx; +	BOOL incomplete; +	CK_RV ret; + +	ASSERT(sess); +	ASSERT(data); +	ASSERT(n_data); + +	if(sess->operation_type != OPERATION_SIGN) +		return CKR_OPERATION_NOT_INITIALIZED; + +	ctx = (CryptoContext*)sess->operation_data; +	switch(ctx->mech_type) +	{ +	case CKM_RSA_PKCS: +		ret = ckcapi_rsa_pkcs_sign_perform(data, n_data, signature, n_signature, +		                                   &ctx->mech_data); +		break; + +	default: +		ASSERT(FALSE); +		ret = CKR_GENERAL_ERROR; +		break; +	} + +	/* Buffer calculation, we don't end operation */ +	incomplete = (ret == CKR_BUFFER_TOO_SMALL || (ret == CKR_OK && !signature)); + +	if(!incomplete) +		cleanup_crypto_operation(sess); + +	return ret; +} + +CK_RV +ckcapi_session_decrypt_init(CkCapiSession* sess, CK_MECHANISM_PTR mech,  +                            CkCapiObjectData *objdata) +{ +	CryptoContext* ctx; +	CK_RV ret; + +	ASSERT(sess); +	ASSERT(mech); +	ASSERT(objdata); + +	if(sess->operation_type != OPERATION_NONE) +		return CKR_OPERATION_ACTIVE; + +	ctx = calloc(1, sizeof(CryptoContext)); +	if(!ctx) +		return CKR_HOST_MEMORY; + +	ctx->mech_type = mech->mechanism; + +	switch(mech->mechanism) +	{ +	case CKM_RSA_PKCS: +		ret = ckcapi_rsa_pkcs_decrypt_init(objdata, &ctx->mech_data); +		ctx->mech_cleanup = ckcapi_rsa_pkcs_decrypt_cleanup; +	default: +		ret = CKR_MECHANISM_INVALID; +	}; + +	if(ret != CKR_OK) +	{ +		free(ctx); +		ASSERT(!sess->operation_data); +		return ret; +	} + +	sess->operation_type = OPERATION_DECRYPT; +	sess->operation_data = ctx; +	sess->operation_cancel = cleanup_crypto_operation; +	return CKR_OK; +} + +CK_RV +ckcapi_session_decrypt(CkCapiSession* sess,  CK_BYTE_PTR encdata, CK_ULONG n_encdata, +                       CK_BYTE_PTR result, CK_ULONG_PTR n_result) +{ +	CryptoContext *ctx; +	BOOL incomplete; +	CK_RV ret; + +	ASSERT(sess); +	ASSERT(encdata); +	ASSERT(n_encdata); + +	if(sess->operation_type != OPERATION_DECRYPT) +		return CKR_OPERATION_NOT_INITIALIZED; + +	ctx = (CryptoContext*)sess->operation_data; +	switch(ctx->mech_type) +	{ +	case CKM_RSA_PKCS: +		ret = ckcapi_rsa_pkcs_decrypt_perform(encdata, n_encdata, result, n_result, +		                                      &ctx->mech_data); +		break; + +	default: +		ASSERT(FALSE); +		ret = CKR_GENERAL_ERROR; +		break; +	} + +	/* Buffer calculation, we don't end operation */ +	incomplete = (ret == CKR_BUFFER_TOO_SMALL || (ret == CKR_OK && !result)); + +	if(!incomplete) +		cleanup_crypto_operation(sess); + +	return ret; +} diff --git a/ckcapi-session.h b/ckcapi-session.h index 6007662..4fb68fa 100644 --- a/ckcapi-session.h +++ b/ckcapi-session.h @@ -22,14 +22,7 @@  #include "ckcapi.h" -/* For operation_type in CkCapiSession */ -enum -{ -	OPERATION_NONE = 0, -	OPERATION_FIND = 1, -}; - -/* Callback to cancel a current operation */ +/* Callback to cleanup a current operation */  typedef void (*CkCapiSessionCancel) (struct _CkCapiSession* sess);  /* Represents an open session */ @@ -95,7 +88,25 @@ CK_RV			ckcapi_session_find				(CkCapiSession* sess,  CK_RV			ckcapi_session_find_final		(CkCapiSession* sess); +/* Start a sign operation on a session */ +CK_RV           ckcapi_session_sign_init        (CkCapiSession* sess,  +                                                 CK_MECHANISM_PTR mech,  +                                                 CkCapiObjectData *objdata); + +/* Perform sign operation */ +CK_RV           ckcapi_session_sign             (CkCapiSession* sess,  +                                                 CK_BYTE_PTR data, CK_ULONG n_data, +                                                 CK_BYTE_PTR sig, CK_ULONG_PTR n_sig); + +/* Start a decrypt operation on a session */ +CK_RV           ckcapi_session_decrypt_init     (CkCapiSession* sess,  +                                                 CK_MECHANISM_PTR mech,  +                                                 CkCapiObjectData *objdata); +/* Perform decrypt operation */ +CK_RV           ckcapi_session_decrypt          (CkCapiSession* sess,  +                                                 CK_BYTE_PTR encdata, CK_ULONG n_encdata, +                                                 CK_BYTE_PTR result, CK_ULONG_PTR n_result);  /* Get object data for an object */  CK_RV			ckcapi_session_get_object_data		(CkCapiSession* sess,  @@ -138,28 +138,39 @@ ckcapi_winerr_to_ckr(DWORD werr)  }  CK_RV -ckcapi_return_data(CK_ATTRIBUTE_PTR attr, CK_VOID_PTR src, DWORD slen) +ckcapi_return_data_raw(CK_VOID_PTR output, CK_ULONG_PTR n_output, +                       CK_VOID_PTR input, CK_ULONG n_input)  { +	ASSERT(n_output); +	ASSERT(input); +  	/* Just asking for the length */ -	if(!attr->pValue) +	if(!output)  	{ -		attr->ulValueLen = slen; +		*n_output = n_input;  		return CKR_OK;  	}  	/* Buffer is too short */ -	if(slen > attr->ulValueLen) +	if(n_input > *n_output)  	{ -		attr->ulValueLen = slen; +		*n_output = n_input;  		return CKR_BUFFER_TOO_SMALL;  	} -	attr->ulValueLen = slen; -	memcpy(attr->pValue, src, slen); +	*n_output = n_input; +	memcpy(output, input, n_input);  	return CKR_OK;  }  CK_RV +ckcapi_return_data(CK_ATTRIBUTE_PTR attr, CK_VOID_PTR input, DWORD n_input) +{ +	return ckcapi_return_data_raw(attr->pValue, &(attr->ulValueLen), +	                              input, n_input); +} + +CK_RV  ckcapi_return_string(CK_ATTRIBUTE_PTR attr, WCHAR* string)  {  	DWORD error; @@ -866,7 +877,7 @@ CC_C_EncryptUpdate(CK_SESSION_HANDLE session, CK_BYTE_PTR part,  	ENTER(C_EncryptUpdate);  	PREREQ(cryptoki_initialized, CKR_CRYPTOKI_NOT_INITIALIZED); -	/* TODO: See if we need to implement this */ +	/* RSA/DSA mechs don't support incremental crypto operations. */  	RETURN(CKR_FUNCTION_NOT_SUPPORTED);  } @@ -877,7 +888,7 @@ CC_C_EncryptFinal(CK_SESSION_HANDLE session, CK_BYTE_PTR last_encrypted_part,  	ENTER(C_EncryptFinal);  	PREREQ(cryptoki_initialized, CKR_CRYPTOKI_NOT_INITIALIZED); -	/* TODO: See if we need to implement this */ +	/* RSA/DSA mechs don't support incremental crypto operations. */  	RETURN(CKR_FUNCTION_NOT_SUPPORTED);  } @@ -885,22 +896,49 @@ static CK_RV  CC_C_DecryptInit(CK_SESSION_HANDLE session, CK_MECHANISM_PTR mechanism,                   CK_OBJECT_HANDLE key)  { +	CkCapiObjectData* objdata; +	CkCapiSession* sess; +	CK_RV ret; +  	ENTER(C_DecryptInit);  	PREREQ(cryptoki_initialized, CKR_CRYPTOKI_NOT_INITIALIZED); +	PREREQ(mechanism, CKR_ARGUMENTS_BAD); +	PREREQ(key, CKR_ARGUMENTS_BAD); -	/* TODO: Implement this */ -	RETURN(CKR_FUNCTION_NOT_SUPPORTED); +	ret = ckcapi_session_get_lock_ref(session, 0, &sess); +	if(ret == CKR_OK) +	{ +		ret = ckcapi_session_get_object_data_for(sess, key, &objdata); +		if(ret == CKR_OK) +			ret = ckcapi_session_decrypt_init(sess, mechanism, objdata); + +		ckcapi_session_unref_unlock(sess); +	} + +	RETURN(ret);  }  static CK_RV  CC_C_Decrypt(CK_SESSION_HANDLE session, CK_BYTE_PTR encrypted_data,               CK_ULONG encrypted_data_len, CK_BYTE_PTR data, CK_ULONG_PTR data_len)  { +	CkCapiSession* sess; +	CK_RV ret; +  	ENTER(C_Decrypt);  	PREREQ(cryptoki_initialized, CKR_CRYPTOKI_NOT_INITIALIZED); +	PREREQ(encrypted_data, CKR_ARGUMENTS_BAD); +	PREREQ(encrypted_data_len, CKR_ARGUMENTS_BAD); -	/* TODO: Implement this */ -	RETURN(CKR_FUNCTION_NOT_SUPPORTED); +	ret = ckcapi_session_get_lock_ref(session, 0, &sess); +	if(ret == CKR_OK) +	{ +		ret = ckcapi_session_decrypt(sess, encrypted_data, encrypted_data_len,  +		                             data, data_len); +		ckcapi_session_unref_unlock(sess); +	} + +	RETURN(ret);  }  static CK_RV @@ -910,7 +948,7 @@ CC_C_DecryptUpdate(CK_SESSION_HANDLE session, CK_BYTE_PTR encrypted_part,  	ENTER(C_DecryptUpdate);  	PREREQ(cryptoki_initialized, CKR_CRYPTOKI_NOT_INITIALIZED); -	/* TODO: Implement this */ +	/* RSA/DSA mechs don't support incremental crypto operations. */  	RETURN(CKR_FUNCTION_NOT_SUPPORTED);  } @@ -921,7 +959,7 @@ CC_C_DecryptFinal(CK_SESSION_HANDLE session, CK_BYTE_PTR pLastPart,  	ENTER(C_DecryptFinal);  	PREREQ(cryptoki_initialized, CKR_CRYPTOKI_NOT_INITIALIZED); -	/* TODO: Implement this */ +	/* RSA/DSA mechs don't support incremental crypto operations. */  	RETURN(CKR_FUNCTION_NOT_SUPPORTED);  } @@ -931,7 +969,7 @@ CC_C_DigestInit(CK_SESSION_HANDLE session, CK_MECHANISM_PTR mechanism)  	ENTER(C_DigestInit);  	PREREQ(cryptoki_initialized, CKR_CRYPTOKI_NOT_INITIALIZED); -	/* TODO: Implement this */ +	/* RSA/DSA mechs don't support digest. */  	RETURN(CKR_FUNCTION_NOT_SUPPORTED);  } @@ -942,7 +980,7 @@ CC_C_Digest(CK_SESSION_HANDLE session, CK_BYTE_PTR data, CK_ULONG data_len,  	ENTER(C_Digest);  	PREREQ(cryptoki_initialized, CKR_CRYPTOKI_NOT_INITIALIZED); -	/* TODO: See if we need to implement this */ +	/* RSA/DSA mechs don't support digest. */  	RETURN(CKR_FUNCTION_NOT_SUPPORTED);  } @@ -952,7 +990,7 @@ CC_C_DigestUpdate(CK_SESSION_HANDLE session, CK_BYTE_PTR part, CK_ULONG part_len  	ENTER(C_DigestUpdate);  	PREREQ(cryptoki_initialized, CKR_CRYPTOKI_NOT_INITIALIZED); -	/* TODO: See if we need to implement this */ +	/* RSA/DSA mechs don't support digest. */  	RETURN(CKR_FUNCTION_NOT_SUPPORTED);  } @@ -962,7 +1000,7 @@ CC_C_DigestKey(CK_SESSION_HANDLE session, CK_OBJECT_HANDLE key)  	ENTER(C_DigestKey);  	PREREQ(cryptoki_initialized, CKR_CRYPTOKI_NOT_INITIALIZED); -	/* TODO: See if we need to implement this */ +	/* RSA/DSA mechs don't support digest. */  	RETURN(CKR_FUNCTION_NOT_SUPPORTED);  } @@ -973,7 +1011,7 @@ CC_C_DigestFinal(CK_SESSION_HANDLE session, CK_BYTE_PTR digest,  	ENTER(C_DigestFinal);  	PREREQ(cryptoki_initialized, CKR_CRYPTOKI_NOT_INITIALIZED); -	/* TODO: See if we need to implement this */ +	/* RSA/DSA mechs don't support digest. */  	RETURN(CKR_FUNCTION_NOT_SUPPORTED);  } @@ -981,22 +1019,48 @@ static CK_RV  CC_C_SignInit(CK_SESSION_HANDLE session, CK_MECHANISM_PTR mechanism,                CK_OBJECT_HANDLE key)  { +	CkCapiObjectData* objdata; +	CkCapiSession* sess; +	CK_RV ret; +  	ENTER(C_SignInit);  	PREREQ(cryptoki_initialized, CKR_CRYPTOKI_NOT_INITIALIZED); +	PREREQ(mechanism, CKR_ARGUMENTS_BAD); +	PREREQ(key, CKR_ARGUMENTS_BAD); -	/* TODO: Implement this */ -	RETURN(CKR_FUNCTION_NOT_SUPPORTED); +	ret = ckcapi_session_get_lock_ref(session, 0, &sess); +	if(ret == CKR_OK) +	{ +		ret = ckcapi_session_get_object_data_for(sess, key, &objdata); +		if(ret == CKR_OK) +			ret = ckcapi_session_sign_init(sess, mechanism, objdata); + +		ckcapi_session_unref_unlock(sess); +	} + +	RETURN(ret);  }  static CK_RV  CC_C_Sign(CK_SESSION_HANDLE session, CK_BYTE_PTR data, CK_ULONG data_len,            CK_BYTE_PTR signature, CK_ULONG_PTR signature_len)  { +	CkCapiSession* sess; +	CK_RV ret; +  	ENTER(C_Sign);  	PREREQ(cryptoki_initialized, CKR_CRYPTOKI_NOT_INITIALIZED); +	PREREQ(data, CKR_ARGUMENTS_BAD); +	PREREQ(data_len, CKR_ARGUMENTS_BAD); -	/* TODO: Implement this */ -	RETURN(CKR_FUNCTION_NOT_SUPPORTED); +	ret = ckcapi_session_get_lock_ref(session, 0, &sess); +	if(ret == CKR_OK) +	{ +		ret = ckcapi_session_sign(sess, data, data_len, signature, signature_len); +		ckcapi_session_unref_unlock(sess); +	} + +	RETURN(ret);  }  static CK_RV @@ -1005,7 +1069,7 @@ CC_C_SignUpdate(CK_SESSION_HANDLE session, CK_BYTE_PTR part, CK_ULONG part_len)  	ENTER(C_SignUpdate);  	PREREQ(cryptoki_initialized, CKR_CRYPTOKI_NOT_INITIALIZED); -	/* TODO: Implement this */ +	/* RSA/DSA mechs don't support incremental crypto operations. */  	RETURN(CKR_FUNCTION_NOT_SUPPORTED);  } @@ -1016,7 +1080,7 @@ CC_C_SignFinal(CK_SESSION_HANDLE session, CK_BYTE_PTR signature,  	ENTER(C_SignFinal);  	PREREQ(cryptoki_initialized, CKR_CRYPTOKI_NOT_INITIALIZED); -	/* TODO: Implement this */ +	/* RSA/DSA mechs don't support incremental crypto operations. */  	RETURN(CKR_FUNCTION_NOT_SUPPORTED);  } @@ -1070,7 +1134,7 @@ CC_C_VerifyUpdate(CK_SESSION_HANDLE session, CK_BYTE_PTR part, CK_ULONG part_len  	ENTER(C_VerifyUpdate);  	PREREQ(cryptoki_initialized, CKR_CRYPTOKI_NOT_INITIALIZED); -	/* TODO: See if we need to implement this */ +	/* RSA/DSA mechs don't support incremental crypto operations. */  	RETURN(CKR_FUNCTION_NOT_SUPPORTED);  } @@ -1081,7 +1145,7 @@ CC_C_VerifyFinal(CK_SESSION_HANDLE session, CK_BYTE_PTR signature,  	ENTER(C_VerifyFinal);  	PREREQ(cryptoki_initialized, CKR_CRYPTOKI_NOT_INITIALIZED); -	/* TODO: See if we need to implement this */ +	/* RSA/DSA mechs don't support incremental crypto operations. */  	RETURN(CKR_FUNCTION_NOT_SUPPORTED);  } @@ -1115,7 +1179,7 @@ CC_C_DigestEncryptUpdate(CK_SESSION_HANDLE session, CK_BYTE_PTR part,  	ENTER(C_DigestEncryptUpdate);  	PREREQ(cryptoki_initialized, CKR_CRYPTOKI_NOT_INITIALIZED); -	/* TODO: See if we need to implement this */ +	/* RSA/DSA mechs don't support incremental crypto operations. */  	RETURN(CKR_FUNCTION_NOT_SUPPORTED);  } @@ -1127,7 +1191,7 @@ CC_C_DecryptDigestUpdate(CK_SESSION_HANDLE session, CK_BYTE_PTR encrypted_part,  	ENTER(C_DecryptDigestUpdate);  	PREREQ(cryptoki_initialized, CKR_CRYPTOKI_NOT_INITIALIZED); -	/* TODO: See if we need to implement this */ +	/* RSA/DSA mechs don't support incremental crypto operations. */  	RETURN(CKR_FUNCTION_NOT_SUPPORTED);  } @@ -1139,7 +1203,7 @@ CC_C_SignEncryptUpdate(CK_SESSION_HANDLE session, CK_BYTE_PTR part,  	ENTER(C_SignEncryptUpdate);  	PREREQ(cryptoki_initialized, CKR_CRYPTOKI_NOT_INITIALIZED); -	/* TODO: See if we need to implement this */ +	/* RSA/DSA mechs don't support incremental crypto operations. */  	RETURN(CKR_FUNCTION_NOT_SUPPORTED);  } @@ -1151,7 +1215,7 @@ CC_C_DecryptVerifyUpdate(CK_SESSION_HANDLE session, CK_BYTE_PTR encrypted_part,  	ENTER(C_DecryptVerifyUpdate);  	PREREQ(cryptoki_initialized, CKR_CRYPTOKI_NOT_INITIALIZED); -	/* TODO: See if we need to implement this */ +	/* RSA/DSA mechs don't support incremental crypto operations. */  	RETURN(CKR_FUNCTION_NOT_SUPPORTED);  } @@ -91,6 +91,9 @@ CK_RV		ckcapi_winerr_to_ckr	(DWORD werr);  CK_RV		ckcapi_return_data		         (CK_ATTRIBUTE_PTR attr,   											  CK_VOID_PTR src, DWORD slen); +CK_RV       ckcapi_return_data_raw           (CK_VOID_PTR output, CK_ULONG_PTR n_output, +                                              CK_VOID_PTR input, CK_ULONG n_input); +  /*   * This stores a string in the output buffer with appropriate   * PKCS#11 codes when the buffer is too short, or the caller @@ -107,6 +110,8 @@ CK_RV       ckcapi_return_reversed_data      (CK_ATTRIBUTE_PTR attr,  /* ------------------------------------------------------------------ */ +typedef void (*CkCapiDestroyFunc)(void* data); +  #ifndef ASSERT  #include "assert.h"  #define ASSERT assert diff --git a/ckcapi.vcproj b/ckcapi.vcproj index 5abc307..8ca8b36 100644 --- a/ckcapi.vcproj +++ b/ckcapi.vcproj @@ -252,6 +252,10 @@  				</FileConfiguration>  			</File>  			<File +				RelativePath=".\ckcapi-der.c" +				> +			</File> +			<File  				RelativePath=".\ckcapi-key.c"  				>  			</File> @@ -276,6 +280,10 @@  				</FileConfiguration>  			</File>  			<File +				RelativePath=".\ckcapi-rsa.c" +				> +			</File> +			<File  				RelativePath="ckcapi-session.c"  				>  				<FileConfiguration @@ -385,6 +393,10 @@  				>  			</File>  			<File +				RelativePath=".\ckcapi-der.h" +				> +			</File> +			<File  				RelativePath=".\ckcapi-key.h"  				>  			</File> @@ -393,6 +405,10 @@  				>  			</File>  			<File +				RelativePath=".\ckcapi-rsa.h" +				> +			</File> +			<File  				RelativePath=".\ckcapi-session.h"  				>  			</File>  | 
