pk11skey.c
来自「支持SSL v2/v3, TLS, PKCS #5, PKCS #7, PKCS」· C语言 代码 · 共 2,251 行 · 第 1/5 页
C
2,251 行
CK_MECHANISM_TYPE mechanism= CKM_INVALID_MECHANISM; /* RC2 only */ SECItem *param = NULL; /* RC2 only */ CK_RC2_CBC_PARAMS *rc2_params = NULL; /* RC2 ONLY */ unsigned int effectiveBits = 0; /* RC2 ONLY */ switch (PK11_GetKeyType(key->type,0)) { case CKK_CDMF: return 40; case CKK_DES: return 56; case CKK_DES3: case CKK_DES2: size = PK11_GetKeyLength(key); if (size == 16) { /* double des */ return 112; /* 16*7 */ } return 168; /* * RC2 has is different than other ciphers in that it allows the user * to deprecating keysize while still requiring all the bits for the * original key. The info * on what the effective key strength is in the parameter for the key. * In S/MIME this parameter is stored in the DER encoded algid. In Our * other uses of RC2, effectiveBits == keyBits, so this code functions * correctly without an algid. */ case CKK_RC2: /* if no algid was provided, fall through to default */ if (!algid) { break; } /* verify that the algid is for RC2 */ mechanism = PK11_AlgtagToMechanism(SECOID_GetAlgorithmTag(algid)); if ((mechanism != CKM_RC2_CBC) && (mechanism != CKM_RC2_ECB)) { break; } /* now get effective bits from the algorithm ID. */ param = PK11_ParamFromAlgid(algid); /* if we couldn't get memory just use key length */ if (param == NULL) { break; } rc2_params = (CK_RC2_CBC_PARAMS *) param->data; /* paranoia... shouldn't happen */ PORT_Assert(param->data != NULL); if (param->data == NULL) { SECITEM_FreeItem(param,PR_TRUE); break; } effectiveBits = (unsigned int)rc2_params->ulEffectiveBits; SECITEM_FreeItem(param,PR_TRUE); param = NULL; rc2_params=NULL; /* paranoia */ /* we have effective bits, is and allocated memory is free, now * we need to return the smaller of effective bits and keysize */ size = PK11_GetKeyLength(key); if ((unsigned int)size*8 > effectiveBits) { return effectiveBits; } return size*8; /* the actual key is smaller, the strength can't be * greater than the actual key size */ default: break; } return PK11_GetKeyLength(key) * 8;}/* Make a Key type to an appropriate signing/verification mechanism */static CK_MECHANISM_TYPEpk11_mapSignKeyType(KeyType keyType){ switch (keyType) { case rsaKey: return CKM_RSA_PKCS; case fortezzaKey: case dsaKey: return CKM_DSA; case dhKey: default: break; } return CKM_INVALID_MECHANISM;}static CK_MECHANISM_TYPEpk11_mapWrapKeyType(KeyType keyType){ switch (keyType) { case rsaKey: return CKM_RSA_PKCS; /* Add fortezza?? */ default: break; } return CKM_INVALID_MECHANISM;}/* * Some non-compliant PKCS #11 vendors do not give us the modulus, so actually * set up a signature to get the signaure length. */static intpk11_backupGetSignLength(SECKEYPrivateKey *key){ PK11SlotInfo *slot = key->pkcs11Slot; CK_MECHANISM mech = {0, NULL, 0 }; PRBool owner = PR_TRUE; CK_SESSION_HANDLE session; CK_ULONG len; CK_RV crv; unsigned char h_data[20] = { 0 }; unsigned char buf[20]; /* obviously to small */ CK_ULONG smallLen = sizeof(buf); mech.mechanism = pk11_mapSignKeyType(key->keyType); session = pk11_GetNewSession(slot,&owner); if (!owner || !(slot->isThreadSafe)) PK11_EnterSlotMonitor(slot); crv = PK11_GETTAB(slot)->C_SignInit(session,&mech,key->pkcs11ID); if (crv != CKR_OK) { if (!owner || !(slot->isThreadSafe)) PK11_ExitSlotMonitor(slot); pk11_CloseSession(slot,session,owner); PORT_SetError( PK11_MapError(crv) ); return -1; } len = 0; crv = PK11_GETTAB(slot)->C_Sign(session,h_data,sizeof(h_data), NULL, &len); /* now call C_Sign with too small a buffer to clear the session state */ (void) PK11_GETTAB(slot)-> C_Sign(session,h_data,sizeof(h_data),buf,&smallLen); if (!owner || !(slot->isThreadSafe)) PK11_ExitSlotMonitor(slot); pk11_CloseSession(slot,session,owner); if (crv != CKR_OK) { PORT_SetError( PK11_MapError(crv) ); return -1; } return len;}/* * get the length of a signature object based on the key */intPK11_SignatureLen(SECKEYPrivateKey *key){ PK11SlotInfo *slot = key->pkcs11Slot; int val; switch (key->keyType) { case rsaKey: val = PK11_GetPrivateModulusLen(key); if (val == -1) { break; /* failed */ } return (unsigned long) val; case fortezzaKey: case dsaKey: return 40; default: break; } PORT_SetError( SEC_ERROR_INVALID_KEY ); return 0;}PK11SlotInfo *PK11_GetSlotFromPrivateKey(SECKEYPrivateKey *key){ PK11SlotInfo *slot = key->pkcs11Slot; slot = PK11_ReferenceSlot(slot); return slot;}/* * Get the modulus length for raw parsing */intPK11_GetPrivateModulusLen(SECKEYPrivateKey *key){ CK_ATTRIBUTE theTemplate = { CKA_MODULUS, NULL, 0 }; PK11SlotInfo *slot = key->pkcs11Slot; CK_RV crv; int length; switch (key->keyType) { case rsaKey: crv = PK11_GetAttributes(NULL, slot, key->pkcs11ID, &theTemplate, 1); if (crv != CKR_OK) { PORT_SetError( PK11_MapError(crv) ); return -1; } length = theTemplate.ulValueLen; if ( *(unsigned char *)theTemplate.pValue == 0) { length--; } if (theTemplate.pValue != NULL) PORT_Free(theTemplate.pValue); return (int) length; case fortezzaKey: case dsaKey: case dhKey: default: break; } if (theTemplate.pValue != NULL) PORT_Free(theTemplate.pValue); PORT_SetError( SEC_ERROR_INVALID_KEY ); return -1;}/* * copy a key (or any other object) on a token */CK_OBJECT_HANDLEPK11_CopyKey(PK11SlotInfo *slot, CK_OBJECT_HANDLE srcObject){ CK_OBJECT_HANDLE destObject; CK_RV crv; PK11_EnterSlotMonitor(slot); crv = PK11_GETTAB(slot)->C_CopyObject(slot->session,srcObject,NULL,0, &destObject); PK11_ExitSlotMonitor(slot); if (crv == CKR_OK) return destObject; PORT_SetError( PK11_MapError(crv) ); return CK_INVALID_KEY;}PK11SymKey *pk11_KeyExchange(PK11SlotInfo *slot,CK_MECHANISM_TYPE type, CK_ATTRIBUTE_TYPE operation, PK11SymKey *symKey);/* * The next two utilities are to deal with the fact that a given operation * may be a multi-slot affair. This creates a new key object that is copied * into the new slot. */PK11SymKey *pk11_CopyToSlot(PK11SlotInfo *slot,CK_MECHANISM_TYPE type, CK_ATTRIBUTE_TYPE operation, PK11SymKey *symKey){ SECStatus rv; PK11SymKey *newKey = NULL; /* Extract the raw key data if possible */ if (symKey->data.data == NULL) { rv = PK11_ExtractKeyValue(symKey); /* KEY is sensitive, we're try key exchanging it. */ if (rv != SECSuccess) { return pk11_KeyExchange(slot, type, operation, symKey); } } newKey = PK11_ImportSymKey(slot, type, symKey->origin, operation, &symKey->data, symKey->cx); if (newKey == NULL) newKey = pk11_KeyExchange(slot,type,operation,symKey); return newKey;}/* * Make sure the slot we are in the correct slot for the operation */static PK11SymKey *pk11_ForceSlot(PK11SymKey *symKey,CK_MECHANISM_TYPE type, CK_ATTRIBUTE_TYPE operation){ PK11SlotInfo *slot = symKey->slot; PK11SymKey *newKey = NULL; if ((slot== NULL) || !PK11_DoesMechanism(slot,type)) { slot = PK11_GetBestSlot(type,symKey->cx); if (slot == NULL) { PORT_SetError( SEC_ERROR_NO_MODULE ); return NULL; } newKey = pk11_CopyToSlot(slot, type, operation, symKey); PK11_FreeSlot(slot); } return newKey;}/* * Use the token to Generate a key. keySize must be 'zero' for fixed key * length algorithms. NOTE: this means we can never generate a DES2 key * from this interface! */PK11SymKey *PK11_TokenKeyGen(PK11SlotInfo *slot, CK_MECHANISM_TYPE type, SECItem *param, int keySize, SECItem *keyid, PRBool isToken, void *wincx){ PK11SymKey *symKey; CK_ATTRIBUTE genTemplate[4]; CK_ATTRIBUTE *attrs = genTemplate; int count = sizeof(genTemplate)/sizeof(genTemplate[0]); CK_SESSION_HANDLE session; CK_MECHANISM mechanism; CK_RV crv; PRBool weird = PR_FALSE; /* hack for fortezza */ CK_BBOOL ckfalse = CK_FALSE; CK_BBOOL cktrue = CK_TRUE; if ((keySize == -1) && (type == CKM_SKIPJACK_CBC64)) { weird = PR_TRUE; keySize = 0; } /* TNH: Isn't this redundant, since "handleKey" will set defaults? */ PK11_SETATTRS(attrs, (!weird) ? CKA_ENCRYPT : CKA_DECRYPT, &cktrue, sizeof(CK_BBOOL)); attrs++; if (keySize != 0) { CK_ULONG key_size = keySize; /* Convert to PK11 type */ PK11_SETATTRS(attrs, CKA_VALUE_LEN, &key_size, sizeof(key_size)); attrs++; } /* Include key id value if provided */ if (keyid) { PK11_SETATTRS(attrs, CKA_ID, keyid->data, keyid->len); attrs++; } if (isToken) { PK11_SETATTRS(attrs, CKA_TOKEN, &cktrue, sizeof(cktrue)); attrs++; } count = attrs - genTemplate; PR_ASSERT(count <= sizeof(genTemplate)/sizeof(CK_ATTRIBUTE)); /* find a slot to generate the key into */ /* Only do slot management if this is not a token key */ if (!isToken && (slot == NULL || !PK11_DoesMechanism(slot,type))) { PK11SlotInfo *bestSlot; bestSlot = PK11_GetBestSlot(type,wincx); /* TNH: references the slot? */ if (bestSlot == NULL) { PORT_SetError( SEC_ERROR_NO_MODULE ); return NULL; } symKey = PK11_CreateSymKey(bestSlot,type,wincx); PK11_FreeSlot(bestSlot); } else { symKey = PK11_CreateSymKey(slot, type, wincx); } if (symKey == NULL) return NULL; symKey->size = keySize; symKey->origin = (!weird) ? PK11_OriginGenerated : PK11_OriginFortezzaHack; /* Initialize the Key Gen Mechanism */ mechanism.mechanism = PK11_GetKeyGen(type); if (mechanism.mechanism == CKM_FAKE_RANDOM) { PORT_SetError( SEC_ERROR_NO_MODULE ); return NULL; } /* Set the parameters for the key gen if provided */ mechanism.pParameter = NULL; mechanism.ulParameterLen = 0; if (param) { mechanism.pParameter = param->data; mechanism.ulParameterLen = param->len; } /* Get session and perform locking */ if (isToken) { session = PK11_GetRWSession(symKey->slot); /* Should always be original slot */ } else { session = symKey->session; pk11_EnterKeyMonitor(symKey); } crv = PK11_GETTAB(symKey->slot)->C_GenerateKey(session, &mechanism, genTemplate, count, &symKey->objectID); /* Release lock and session */ if (isToken) { PK11_RestoreROSession(symKey->slot, session); } else { pk11_ExitKeyMonitor(symKey); } if (crv != CKR_OK) { PK11_FreeSymKey(symKey); PORT_SetError( PK11_MapError(crv) ); return NULL; } return symKey;}PK11SymKey *PK11_KeyGen(PK11SlotInfo *slot, CK_MECHANISM_TYPE type, SECItem *param, int keySize, void *wincx){ return PK11_TokenKeyGen(slot, type, param, keySize, 0, PR_FALSE, wincx);}/* --- */PK11SymKey *PK11_GenDES3TokenKey(PK11SlotInfo *slot, SECItem *keyid, void *cx){ return PK11_TokenKeyGen(slot, CKM_DES3_CBC, 0, 0, keyid, PR_TRUE, cx);}/* * PKCS #11 pairwise consistency check utilized to validate key pair. */static SECStatuspk11_PairwiseConsistencyCheck(SECKEYPublicKey *pubKey, SECKEYPrivateKey *privKey, CK_MECHANISM *mech, void* wincx ){ /* Variables used for Encrypt/Decrypt functions. */ unsigned char *known_message = (unsigned char *)"Known Crypto Message"; CK_BBOOL isEncryptable = CK_FALSE; CK_BBOOL canSignVerify = CK_FALSE; CK_BBOOL isDerivable = CK_FALSE; unsigned char plaintext[PAIRWISE_MESSAGE_LENGTH]; CK_ULONG bytes_decrypted; PK11SlotInfo *slot; CK_OBJECT_HANDLE id; unsigned char *ciphertext; unsigned char *text_compared; CK_ULONG max_bytes_encrypted; CK_ULONG bytes_encrypted; CK_ULONG bytes_compared; CK_RV crv; /* Variables used for Signature/Verification functions. */ unsigned char *known_digest = (unsigned char *)"Mozilla Rules World!"; SECItem signature; SECItem digest; /* always uses SHA-1 digest */ int signature_length; SECStatus rv; /**************************************************/ /* Pairwise Consistency Check of Encrypt/Decrypt. */ /**************************************************/ isEncryptable = PK11_HasAttributeSet( privKey->pkcs11Slot,
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?