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