From ae56e5c788e3ed6c60d98d445574d3042aaae24f Mon Sep 17 00:00:00 2001 From: Stef Walter Date: Tue, 9 Dec 2008 20:59:55 +0000 Subject: Move into module folder --- p11-capi-rsa.c | 415 --------------------------------------------------------- 1 file changed, 415 deletions(-) delete mode 100644 p11-capi-rsa.c (limited to 'p11-capi-rsa.c') diff --git a/p11-capi-rsa.c b/p11-capi-rsa.c deleted file mode 100644 index 18fc4eb..0000000 --- a/p11-capi-rsa.c +++ /dev/null @@ -1,415 +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-der.h" -#include "p11-capi-key.h" -#include "p11-capi-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((P11C_DER_SEQUENCE | P11C_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 = p11c_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((P11C_DER_SEQUENCE | P11C_DER_CONSTRUCTED) != *algid) - return NULL; - - oid = p11c_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 = p11c_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(P11C_DER_OCTET_STRING != *hash_data) - return NULL; - - /* get the real raw hash */ - return p11c_der_unwrap(hash_data, n_algid - (hash_data - algid), - n_hash, NULL); -} - -CK_RV -p11c_rsa_pkcs_sign_init(P11cObjectData *keydata, void** operation) -{ - CRYPT_KEY_PROV_INFO* prov_info; - - ASSERT(keydata); - ASSERT(operation); - ASSERT(!*operation); - - prov_info = p11c_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 -p11c_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; - P11cObjectData* 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 = (P11cObjectData*)*operation; - - prov_info = p11c_key_object_data_get_prov_info(keydata); - ASSERT(prov_info); - - /* Calculate the number of bits */ - bits = p11c_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) - p11c_reverse_memory(signature, *n_signature); - - capifail = FALSE; - ret = CKR_OK; - } - } - } - } - } - - if(capifail) - ret = p11c_winerr_to_ckr(GetLastError()); - - if(hash) - CryptDestroyHash(hash); - if(prov) - CryptReleaseContext(prov, 0); - - return ret; -} - -void -p11c_rsa_pkcs_sign_cleanup (void* operation) -{ - /* Nothing to do */ -} - - -CK_RV -p11c_rsa_pkcs_decrypt_init(P11cObjectData* keydata, void** operation) -{ - CRYPT_KEY_PROV_INFO* prov_info; - - ASSERT(keydata); - ASSERT(operation); - ASSERT(!*operation); - - prov_info = p11c_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 -p11c_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; - P11cObjectData* 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 = (P11cObjectData*)*operation; - - prov_info = p11c_key_object_data_get_prov_info(keydata); - ASSERT(prov_info); - - /* Calculate the number of bits */ - bits = p11c_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); - p11c_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 = p11c_winerr_to_ckr(error); - }; - } - - /* Copy the memory out to the result buffer */ - if(ret == CKR_OK) - ret = p11c_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 -p11c_rsa_pkcs_decrypt_cleanup(void* operation) -{ - /* Nothing to do */ -} - -void -p11c_rsa_pkcs_get_info(CK_MECHANISM_TYPE mech, CK_MECHANISM_INFO_PTR info) -{ - ASSERT(mech == CKM_RSA_PKCS); - ASSERT(info != NULL); - - info->ulMinKeySize = 384; - info->ulMaxKeySize = 16384; - info->flags = 0; -} -- cgit v1.2.3