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