pk11skey.c

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

C
2,251
字号
/* * 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 the Symkey wrapper and the PKCS context * Interfaces. */#include "seccomon.h"#include "secmod.h"#include "prlock.h"#include "secmodi.h"#include "pkcs11.h"#include "pk11func.h"#include "secitem.h"#include "key.h"#include "secoid.h"#include "secasn1.h"#include "sechash.h"#include "cert.h"#include "secerr.h"#define PAIRWISE_SECITEM_TYPE			siBuffer#define PAIRWISE_DIGEST_LENGTH			SHA1_LENGTH /* 160-bits */#define PAIRWISE_MESSAGE_LENGTH			20          /* 160-bits *//* forward static declarations. */static PK11SymKey *pk11_DeriveWithTemplate(PK11SymKey *baseKey, 	CK_MECHANISM_TYPE derive, SECItem *param, CK_MECHANISM_TYPE target, 	CK_ATTRIBUTE_TYPE operation, int keySize, CK_ATTRIBUTE *userAttr, 	unsigned int numAttrs);/* * strip leading zero's from key material */voidpk11_SignedToUnsigned(CK_ATTRIBUTE *attrib) {    char *ptr = (char *)attrib->pValue;    unsigned long len = attrib->ulValueLen;    while (len && (*ptr == 0)) {	len--;	ptr++;    }    attrib->pValue = ptr;    attrib->ulValueLen = len;}/* * get a new session on a slot. If we run out of session, use the slot's * 'exclusive' session. In this case owner becomes false. */static CK_SESSION_HANDLEpk11_GetNewSession(PK11SlotInfo *slot,PRBool *owner){    CK_SESSION_HANDLE session;    *owner =  PR_TRUE;    if (!slot->isThreadSafe) PK11_EnterSlotMonitor(slot);    if ( PK11_GETTAB(slot)->C_OpenSession(slot->slotID,CKF_SERIAL_SESSION, 			slot,pk11_notify,&session) != CKR_OK) {	*owner = PR_FALSE;	session = slot->session;    }    if (!slot->isThreadSafe) PK11_ExitSlotMonitor(slot);    return session;}static voidpk11_CloseSession(PK11SlotInfo *slot,CK_SESSION_HANDLE session,PRBool owner){    if (!owner) return;    if (!slot->isThreadSafe) PK11_EnterSlotMonitor(slot);    (void) PK11_GETTAB(slot)->C_CloseSession(session);    if (!slot->isThreadSafe) PK11_ExitSlotMonitor(slot);}SECStatusPK11_CreateNewObject(PK11SlotInfo *slot, CK_SESSION_HANDLE session,				CK_ATTRIBUTE *theTemplate, int count, 				PRBool token, CK_OBJECT_HANDLE *objectID){	CK_SESSION_HANDLE rwsession;	CK_RV crv;	SECStatus rv = SECSuccess;	rwsession = session;	if (rwsession == CK_INVALID_SESSION) {	    if (token) {		rwsession =  PK11_GetRWSession(slot);	    } else { 		rwsession =  slot->session;		PK11_EnterSlotMonitor(slot);	    }	}	crv = PK11_GETTAB(slot)->C_CreateObject(rwsession, theTemplate,							count,objectID);	if(crv != CKR_OK) {	    PORT_SetError( PK11_MapError(crv) );	    rv = SECFailure;	}	if (session == CK_INVALID_SESSION) {	    if (token) {		PK11_RestoreROSession(slot, rwsession);	    } else {		PK11_ExitSlotMonitor(slot);	    }        }	return rv;}static voidpk11_EnterKeyMonitor(PK11SymKey *symKey) {    if (!symKey->sessionOwner || !(symKey->slot->isThreadSafe)) 	PK11_EnterSlotMonitor(symKey->slot);}static voidpk11_ExitKeyMonitor(PK11SymKey *symKey) {    if (!symKey->sessionOwner || !(symKey->slot->isThreadSafe))     	PK11_ExitSlotMonitor(symKey->slot);}static PK11SymKey *pk11SymKeyHead = NULL;static PK11SymKey *pk11_getKeyFromList(PK11SlotInfo *slot) {    PK11SymKey *symKey = NULL;    PK11_USE_THREADS(PR_Lock(slot->freeListLock);)    if (slot->freeSymKeysHead) {    	symKey = slot->freeSymKeysHead;	slot->freeSymKeysHead = symKey->next;	slot->keyCount--;    }    PK11_USE_THREADS(PR_Unlock(slot->freeListLock);)    if (symKey) {	symKey->next = NULL;	if (!symKey->sessionOwner)    	    symKey->session = pk11_GetNewSession(slot,&symKey->sessionOwner);	return symKey;    }    symKey = (PK11SymKey *)PORT_ZAlloc(sizeof(PK11SymKey));    if (symKey == NULL) {	return NULL;    }    symKey->refLock = PR_NewLock();    if (symKey->refLock == NULL) {	PORT_Free(symKey);	return NULL;    }    symKey->session = pk11_GetNewSession(slot,&symKey->sessionOwner);    symKey->next = NULL;    return symKey;}voidPK11_CleanKeyList(PK11SlotInfo *slot){    PK11SymKey *symKey = NULL;    while (slot->freeSymKeysHead) {    	symKey = slot->freeSymKeysHead;	slot->freeSymKeysHead = symKey->next;	pk11_CloseSession(symKey->slot, symKey->session,symKey->sessionOwner);	PK11_USE_THREADS(PR_DestroyLock(symKey->refLock);)	PORT_Free(symKey);    };    return;}/* * create a symetric key: *      Slot is the slot to create the key in. *      type is the mechainism type  */PK11SymKey *PK11_CreateSymKey(PK11SlotInfo *slot, CK_MECHANISM_TYPE type, void *wincx){    PK11SymKey *symKey = pk11_getKeyFromList(slot);    if (symKey == NULL) {	return NULL;    }    symKey->type = type;    symKey->data.data = NULL;    symKey->data.len = 0;    symKey->owner = PR_TRUE;    symKey->objectID = CK_INVALID_KEY;    symKey->slot = slot;    symKey->series = slot->series;    symKey->cx = wincx;    symKey->size = 0;    symKey->refCount = 1;    symKey->origin = PK11_OriginNULL;    symKey->origin = PK11_OriginNULL;    PK11_ReferenceSlot(slot);    return symKey;}/* * destroy a symetric key */voidPK11_FreeSymKey(PK11SymKey *symKey){    PRBool destroy = PR_FALSE;    PK11SlotInfo *slot;    PRBool freeit = PR_TRUE;    PK11_USE_THREADS(PR_Lock(symKey->refLock);)     if (symKey->refCount-- == 1) {	destroy= PR_TRUE;    }    PK11_USE_THREADS(PR_Unlock(symKey->refLock);)    if (destroy) {	if ((symKey->owner) && symKey->objectID != CK_INVALID_KEY) {	    pk11_EnterKeyMonitor(symKey);	    (void) PK11_GETTAB(symKey->slot)->		C_DestroyObject(symKey->session, symKey->objectID);	    pk11_ExitKeyMonitor(symKey);	}	if (symKey->data.data) {	    PORT_Memset(symKey->data.data, 0, symKey->data.len);	    PORT_Free(symKey->data.data);	}        slot = symKey->slot;        PK11_USE_THREADS(PR_Lock(slot->freeListLock);)	if (slot->keyCount < slot->maxKeyCount) {	   symKey->next = slot->freeSymKeysHead;	   slot->freeSymKeysHead = symKey;	   slot->keyCount++;	   symKey->slot = NULL;	   freeit = PR_FALSE;        }	PK11_USE_THREADS(PR_Unlock(slot->freeListLock);)        if (freeit) {	    pk11_CloseSession(symKey->slot, symKey->session,							symKey->sessionOwner);	    PK11_USE_THREADS(PR_DestroyLock(symKey->refLock);)	    PORT_Free(symKey);	}	PK11_FreeSlot(slot);    }}PK11SymKey *PK11_ReferenceSymKey(PK11SymKey *symKey){    PK11_USE_THREADS(PR_Lock(symKey->refLock);)    symKey->refCount++;    PK11_USE_THREADS(PR_Unlock(symKey->refLock);)    return symKey;}/* * turn key handle into an appropriate key object */PK11SymKey *PK11_SymKeyFromHandle(PK11SlotInfo *slot, PK11SymKey *parent, PK11Origin origin,    CK_MECHANISM_TYPE type, CK_OBJECT_HANDLE keyID, PRBool owner, void *wincx){    PK11SymKey *symKey;    if (keyID == CK_INVALID_KEY) {	return NULL;    }    symKey = PK11_CreateSymKey(slot,type,wincx);    if (symKey == NULL) {	return NULL;    }    symKey->objectID = keyID;    symKey->origin = origin;    symKey->owner = owner;    /* adopt the parent's session */    /* This is only used by SSL. What we really want here is a session     * structure with a ref count so  the session goes away only after all the     * keys do. */    if (owner && parent) {	pk11_CloseSession(symKey->slot, symKey->session,symKey->sessionOwner);	symKey->sessionOwner = parent->sessionOwner;	symKey->session = parent->session;	parent->sessionOwner = PR_FALSE;    }    return symKey;}/* * turn key handle into an appropriate key object */PK11SymKey *PK11_GetWrapKey(PK11SlotInfo *slot, int wrap, CK_MECHANISM_TYPE type,						    int series, void *wincx){    PK11SymKey *symKey = NULL;    if (slot->series != series) return NULL;    if (slot->refKeys[wrap] == CK_INVALID_KEY) return NULL;    if (type == CKM_INVALID_MECHANISM) type = slot->wrapMechanism;    symKey = PK11_SymKeyFromHandle(slot, NULL, PK11_OriginDerive,		 slot->wrapMechanism, slot->refKeys[wrap], PR_FALSE, wincx);    return symKey;}voidPK11_SetWrapKey(PK11SlotInfo *slot, int wrap, PK11SymKey *wrapKey){    /* save the handle and mechanism for the wrapping key */    /* mark the key and session as not owned by us to they don't get freed     * when the key goes way... that lets us reuse the key later */    slot->refKeys[wrap] = wrapKey->objectID;    wrapKey->owner = PR_FALSE;    wrapKey->sessionOwner = PR_FALSE;    slot->wrapMechanism = wrapKey->type;}CK_MECHANISM_TYPEPK11_GetMechanism(PK11SymKey *symKey){    return symKey->type;}/* * figure out if a key is still valid or if it is stale. */PRBoolPK11_VerifyKeyOK(PK11SymKey *key) {    if (!PK11_IsPresent(key->slot)) {	return PR_FALSE;    }    return (PRBool)(key->series == key->slot->series);}static PK11SymKey *pk11_ImportSymKeyWithTempl(PK11SlotInfo *slot, CK_MECHANISM_TYPE type,                  PK11Origin origin, CK_ATTRIBUTE *keyTemplate, 		  unsigned int templateCount, SECItem *key, void *wincx){    PK11SymKey *    symKey;    SECStatus	    rv;    symKey = PK11_CreateSymKey(slot,type,wincx);    if (symKey == NULL) {	return NULL;    }    symKey->size = key->len;    PK11_SETATTRS(&keyTemplate[templateCount], CKA_VALUE, key->data, key->len);    templateCount++;    if (SECITEM_CopyItem(NULL,&symKey->data,key) != SECSuccess) {	PK11_FreeSymKey(symKey);	return NULL;    }    symKey->origin = origin;    /* import the keys */    rv = PK11_CreateNewObject(slot, symKey->session, keyTemplate,		 	templateCount, PR_FALSE, &symKey->objectID);    if ( rv != SECSuccess) {	PK11_FreeSymKey(symKey);	return NULL;    }    return symKey;}/* * turn key bits into an appropriate key object */PK11SymKey *PK11_ImportSymKey(PK11SlotInfo *slot, CK_MECHANISM_TYPE type,     PK11Origin origin, CK_ATTRIBUTE_TYPE operation, SECItem *key,void *wincx){    PK11SymKey *    symKey;    unsigned int    templateCount = 0;    CK_OBJECT_CLASS keyClass 	= CKO_SECRET_KEY;    CK_KEY_TYPE     keyType 	= CKK_GENERIC_SECRET;    CK_BBOOL        cktrue 	= CK_TRUE; /* sigh */    CK_ATTRIBUTE    keyTemplate[5];    CK_ATTRIBUTE *  attrs 	= keyTemplate;    PK11_SETATTRS(attrs, CKA_CLASS, &keyClass, sizeof(keyClass) ); attrs++;    PK11_SETATTRS(attrs, CKA_KEY_TYPE, &keyType, sizeof(keyType) ); attrs++;    PK11_SETATTRS(attrs, operation, &cktrue, 1); attrs++;    /* PK11_SETATTRS(attrs, CKA_VALUE, key->data, key->len); attrs++; */    templateCount = attrs - keyTemplate;    PR_ASSERT(templateCount <= sizeof(keyTemplate)/sizeof(CK_ATTRIBUTE));    keyType = PK11_GetKeyType(type,key->len);    symKey = pk11_ImportSymKeyWithTempl(slot, type, origin, keyTemplate,     					templateCount, key, wincx);    return symKey;}/* * import a public key into the desired slot */CK_OBJECT_HANDLEPK11_ImportPublicKey(PK11SlotInfo *slot, SECKEYPublicKey *pubKey, 								PRBool isToken){    CK_BBOOL cktrue = CK_TRUE;    CK_BBOOL ckfalse = CK_FALSE;    CK_OBJECT_CLASS keyClass = CKO_PUBLIC_KEY;    CK_KEY_TYPE keyType = CKK_GENERIC_SECRET;

⌨️ 快捷键说明

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