pkcs11c.c

来自「支持SSL v2/v3, TLS, PKCS #5, PKCS #7, PKCS」· C语言 代码 · 共 2,203 行 · 第 1/5 页

C
2,203
字号
/* * 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 Netscape are  * Copyright (C) 1994-2000 Netscape Communications Corporation.  All * Rights Reserved. *  * Contributor(s): *  * Alternatively, the contents of this file may be used under the * terms of the GNU General Public License Version 2 or later (the * "GPL"), in which case the provisions of the GPL are applicable  * instead of those above.  If you wish to allow use of your  * version of this file only under the terms of the GPL and not to * allow others to use your version of this file under the MPL, * indicate your decision by deleting the provisions above and * replace them with the notice and other provisions required by * the GPL.  If you do not delete the provisions above, a recipient * may use your version of this file under either the MPL or the * GPL. *//* * This file implements PKCS 11 on top of our existing security modules * * For more information about PKCS 11 See PKCS 11 Token Inteface Standard. *   This implementation has two slots: *	slot 1 is our generic crypto support. It does not require login. *   It supports Public Key ops, and all they bulk ciphers and hashes.  *   It can also support Private Key ops for imported Private keys. It does  *   not have any token storage. *	slot 2 is our private key support. It requires a login before use. It *   can store Private Keys and Certs as token objects. Currently only private *   keys and their associated Certificates are saved on the token. * *   In this implementation, session objects are only visible to the session *   that created or generated them. */#include "seccomon.h"#include "secitem.h"#include "secport.h"#include "blapi.h"#include "pkcs11.h"#include "pkcs11i.h"#include "keylow.h"#include "cert.h"#include "sechash.h"#include "secder.h"#include "secdig.h"#include "secpkcs5.h"	/* We do PBE below */#include "pkcs11t.h"#include "secoid.h"#include "alghmac.h"#include "softoken.h"#include "secasn1.h"#include "secmodi.h"#include "certdb.h"#include "ssl3prot.h" 	/* for SSL3_RANDOM_LENGTH */#define __PASTE(x,y)    x##y/* * we renamed all our internal functions, get the correct * definitions for them... */ #undef CK_PKCS11_FUNCTION_INFO#undef CK_NEED_ARG_LIST#define CK_EXTERN extern#define CK_PKCS11_FUNCTION_INFO(func) \		CK_RV __PASTE(NS,func)#define CK_NEED_ARG_LIST	1 #include "pkcs11f.h"/* forward static declaration. */static SECStatus pk11_PRF(const SECItem *secret, const char *label,                           SECItem *seed, SECItem *result);  #define PK11_OFFSETOF(str, memb) ((PRPtrdiff)(&(((str *)0)->memb)))static void pk11_Null(void *data, PRBool freeit){    return;} /* * free routines.... Free local type  allocated data, and convert * other free routines to the destroy signature. */static voidpk11_FreePrivKey(SECKEYLowPrivateKey *key, PRBool freeit){    SECKEY_LowDestroyPrivateKey(key);}static voidpk11_HMAC_Destroy(HMACContext *context, PRBool freeit){    HMAC_Destroy(context);}static voidpk11_Space(void *data, PRBool freeit){    PORT_Free(data);} static void pk11_FreeSignInfo(PK11HashSignInfo *data, PRBool freeit){    SECKEY_LowDestroyPrivateKey(data->key);    PORT_Free(data);} static DSAPublicKey *DSA_CreateVerifyContext(SECKEYLowPublicKey *pubKey){    PLArenaPool * arena;    DSAPublicKey * dsaKey;    SECStatus      rv;    arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);    if (!arena) goto loser;     dsaKey = (DSAPublicKey *)PORT_ArenaZAlloc(arena, sizeof (DSAPublicKey));    if (!dsaKey) goto loser;    dsaKey->params.arena = arena;#define COPY_DSA_ITEM(item) \    rv = SECITEM_CopyItem(arena, &dsaKey->item, &pubKey->u.dsa.item); \    if (rv != SECSuccess) goto loser;    COPY_DSA_ITEM(params.prime);    COPY_DSA_ITEM(params.subPrime);    COPY_DSA_ITEM(params.base);    COPY_DSA_ITEM(publicValue);    return dsaKey;loser:    if (arena)	PORT_FreeArena(arena, PR_TRUE);    return NULL;#undef COPY_DSA_ITEM}static void DSA_DestroyVerifyContext(DSAPublicKey * key){    if (key && key->params.arena)	PORT_FreeArena(key->params.arena, PR_TRUE);}static DSAPrivateKey *DSA_CreateSignContext(SECKEYLowPrivateKey *privKey){    PLArenaPool *  arena;    DSAPrivateKey * dsaKey;    SECStatus       rv;    arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);    if (!arena) goto loser;     dsaKey = (DSAPrivateKey *)PORT_ArenaZAlloc(arena, sizeof (DSAPrivateKey));    if (!dsaKey) goto loser;    dsaKey->params.arena = arena;#define COPY_DSA_ITEM(item) \    rv = SECITEM_CopyItem(arena, &dsaKey->item, &privKey->u.dsa.item); \    if (rv != SECSuccess) goto loser;    COPY_DSA_ITEM(params.prime);    COPY_DSA_ITEM(params.subPrime);    COPY_DSA_ITEM(params.base);    COPY_DSA_ITEM(publicValue);    COPY_DSA_ITEM(privateValue);    return dsaKey;loser:    if (arena)	PORT_FreeArena(arena, PR_TRUE);    return NULL;#undef COPY_DSA_ITEM}static void DSA_DestroySignContext(DSAPrivateKey * key){    if (key && key->params.arena)	PORT_FreeArena(key->params.arena, PR_TRUE);}/* * turn a CDMF key into a des key. CDMF is an old IBM scheme to export DES by * Deprecating a full des key to 40 bit key strenth. */static CK_RVpk11_cdmf2des(unsigned char *cdmfkey, unsigned char *deskey){    unsigned char key1[8] = { 0xc4, 0x08, 0xb0, 0x54, 0x0b, 0xa1, 0xe0, 0xae };    unsigned char key2[8] = { 0xef, 0x2c, 0x04, 0x1c, 0xe6, 0x38, 0x2f, 0xe6 };    unsigned char enc_src[8];    unsigned char enc_dest[8];    unsigned int leng,i;    DESContext *descx;    SECStatus rv;            /* zero the parity bits */    for (i=0; i < 8; i++) {	enc_src[i] = cdmfkey[i] & 0xfe;    }    /* encrypt with key 1 */    descx = DES_CreateContext(key1, NULL, NSS_DES, PR_TRUE);    if (descx == NULL) return CKR_HOST_MEMORY;    rv = DES_Encrypt(descx, enc_dest, &leng, 8, enc_src, 8);    DES_DestroyContext(descx,PR_TRUE);    if (rv != SECSuccess) return CKR_DEVICE_ERROR;    /* xor source with des, zero the parity bits and depricate the key*/    for (i=0; i < 8; i++) {	if (i & 1) {	    enc_src[i] = (enc_src[i] ^ enc_dest[i]) & 0xfe;	} else {	    enc_src[i] = (enc_src[i] ^ enc_dest[i]) & 0x0e;	}    }    /* encrypt with key 2 */    descx = DES_CreateContext(key2, NULL, NSS_DES, PR_TRUE);    if (descx == NULL) return CKR_HOST_MEMORY;    rv = DES_Encrypt(descx, deskey, &leng, 8, enc_src, 8);    DES_DestroyContext(descx,PR_TRUE);    if (rv != SECSuccess) return CKR_DEVICE_ERROR;    /* set the corret parity on our new des key */	    pk11_FormatDESKey(deskey, 8);    return CKR_OK;}static CK_RVpk11_EncryptInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism,		 CK_OBJECT_HANDLE hKey, CK_ATTRIBUTE_TYPE etype,		 PK11ContextType contextType);/* * Calculate a Lynx checksum for CKM_LYNX_WRAP mechanism. */static CK_RVpk11_calcLynxChecksum(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hWrapKey,	unsigned char *checksum, unsigned char *key, CK_ULONG len){    CK_BYTE E[10];    CK_ULONG Elen = sizeof (E);    CK_BYTE C[8];    CK_ULONG Clen = sizeof (C);    unsigned short sum1 = 0, sum2 = 0;    CK_MECHANISM mech = { CKM_DES_ECB, NULL, 0 };    int i;    CK_RV crv;    if (len != 8) return CKR_WRAPPED_KEY_LEN_RANGE;        /* zero the parity bits */    for (i=0; i < 8; i++) {	sum1 = sum1 + key[i];	sum2 = sum2 + sum1;    }    /* encrypt with key 1 */    crv = pk11_EncryptInit(hSession,&mech,hWrapKey,CKA_WRAP, PK11_ENCRYPT);    if (crv != CKR_OK) return crv;    crv = NSC_Encrypt(hSession,key,len,E,&Elen);    if (crv != CKR_OK) return crv;    E[8] = (sum2 >> 8) & 0xff;    E[9] = sum2 & 0xff;    crv = pk11_EncryptInit(hSession,&mech,hWrapKey,CKA_WRAP, PK11_ENCRYPT);    if (crv != CKR_OK) return crv;    crv = NSC_Encrypt(hSession,&E[2],len,C,&Clen);    if (crv != CKR_OK) return crv;    checksum[0] = C[6];    checksum[1] = C[7];        return CKR_OK;}/* NSC_DestroyObject destroys an object. */CK_RVNSC_DestroyObject(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject){    PK11Slot *slot = pk11_SlotFromSessionHandle(hSession);    PK11Session *session;    PK11Object *object;    PK11FreeStatus status;    /*     * This whole block just makes sure we really can destroy the     * requested object.     */    session = pk11_SessionFromHandle(hSession);    if (session == NULL) {        return CKR_SESSION_HANDLE_INVALID;    }    object = pk11_ObjectFromHandle(hObject,session);    if (object == NULL) {	pk11_FreeSession(session);	return CKR_OBJECT_HANDLE_INVALID;    }    /* don't destroy a private object if we aren't logged in */    if ((!slot->isLoggedIn) && (slot->needLogin) &&				(pk11_isTrue(object,CKA_PRIVATE))) {	pk11_FreeSession(session);	pk11_FreeObject(object);	return CKR_USER_NOT_LOGGED_IN;    }    /* don't destroy a token object if we aren't in a rw session */    if (((session->info.flags & CKF_RW_SESSION) == 0) &&				(pk11_isTrue(object,CKA_TOKEN))) {	pk11_FreeSession(session);	pk11_FreeObject(object);	return CKR_SESSION_READ_ONLY;    }    pk11_DeleteObject(session,object);    pk11_FreeSession(session);    /*     * get some indication if the object is destroyed. Note: this is not     * 100%. Someone may have an object reference outstanding (though that     * should not be the case by here. Also note that the object is "half"     * destroyed. Our internal representation is destroyed, but it may still     * be in the data base.     */    status = pk11_FreeObject(object);    return (status != PK11_DestroyFailure) ? CKR_OK : CKR_DEVICE_ERROR;}/* ************** Crypto Functions:     Utilities ************************ *//*  * return a context based on the PK11Context type. */PK11SessionContext *pk11_ReturnContextByType(PK11Session *session, PK11ContextType type){    switch (type) {	case PK11_ENCRYPT:	case PK11_DECRYPT:	    return session->enc_context;	case PK11_HASH:	    return session->hash_context;	case PK11_SIGN:	case PK11_SIGN_RECOVER:	case PK11_VERIFY:	case PK11_VERIFY_RECOVER:	    return session->hash_context;    }    return NULL;}/*  * change a context based on the PK11Context type. */voidpk11_SetContextByType(PK11Session *session, PK11ContextType type, 						PK11SessionContext *context){    switch (type) {	case PK11_ENCRYPT:	case PK11_DECRYPT:	    session->enc_context = context;	    break;	case PK11_HASH:	    session->hash_context = context;	    break;	case PK11_SIGN:	case PK11_SIGN_RECOVER:	case PK11_VERIFY:	case PK11_VERIFY_RECOVER:	    session->hash_context = context;	    break;    }    return;}/* * code to grab the context. Needed by every C_XXXUpdate, C_XXXFinal, * and C_XXX function. The function takes a session handle, the context type, * and wether or not the session needs to be multipart. It returns the context, * and optionally returns the session pointer (if sessionPtr != NULL) if session * pointer is returned, the caller is responsible for freeing it. */static CK_RVpk11_GetContext(CK_SESSION_HANDLE handle,PK11SessionContext **contextPtr,	PK11ContextType type, PRBool needMulti, PK11Session **sessionPtr){    PK11Session *session;    PK11SessionContext *context;    session = pk11_SessionFromHandle(handle);    if (session == NULL) return CKR_SESSION_HANDLE_INVALID;    context = pk11_ReturnContextByType(session,type);    /* make sure the context is valid */    if((context==NULL)||(context->type!=type)||(needMulti&&!(context->multi))){        pk11_FreeSession(session);	return CKR_OPERATION_NOT_INITIALIZED;    }    *contextPtr = context;    if (sessionPtr != NULL) {	*sessionPtr = session;    } else {	pk11_FreeSession(session);    }

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?