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 + -
显示快捷键?