pkcs11c.c

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

C
2,203
字号
    context->cipherInfo  = (void *) prf_cx;    context->hashUpdate  = (PK11Hash)    pk11_TLSPRFHashUpdate;    context->end         = (PK11End)     pk11_TLSPRFEnd;    context->update      = (PK11Cipher)  pk11_TLSPRFUpdate;    context->verify      = (PK11Verify)  pk11_TLSPRFVerify;    context->destroy     = (PK11Destroy) pk11_Null;    context->hashdestroy = (PK11Destroy) pk11_TLSPRFHashDestroy;    crv = CKR_OK;done:    if (keyVal) 	pk11_FreeAttribute(keyVal);    return crv;}/* ************** Crypto Functions:     Sign  ************************ *//* * Check if We're using CBCMacing and initialize the session context if we are. */static CK_RVpk11_InitCBCMac(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, 	CK_OBJECT_HANDLE hKey, CK_ATTRIBUTE_TYPE keyUsage,						 PK11ContextType contextType)	{    CK_MECHANISM cbc_mechanism;    CK_ULONG mac_bytes = PK11_INVALID_MAC_SIZE;    CK_RC2_CBC_PARAMS rc2_params;#if NSS_SOFTOKEN_DOES_RC5    CK_RC5_CBC_PARAMS rc5_params;    CK_RC5_MAC_GENERAL_PARAMS *rc5_mac;#endif    unsigned char ivBlock[PK11_MAX_BLOCK_SIZE];    PK11SessionContext *context;    CK_RV crv;    int blockSize;    switch (pMechanism->mechanism) {    case CKM_RC2_MAC_GENERAL:	mac_bytes = 	    ((CK_RC2_MAC_GENERAL_PARAMS *)pMechanism->pParameter)->ulMacLength;	/* fall through */    case CKM_RC2_MAC:	/* this works because ulEffectiveBits is in the same place in both the	 * CK_RC2_MAC_GENERAL_PARAMS and CK_RC2_CBC_PARAMS */	rc2_params.ulEffectiveBits = ((CK_RC2_MAC_GENERAL_PARAMS *)				pMechanism->pParameter)->ulEffectiveBits;	PORT_Memset(rc2_params.iv,0,sizeof(rc2_params.iv));	cbc_mechanism.mechanism = CKM_RC2_CBC;	cbc_mechanism.pParameter = &rc2_params;	cbc_mechanism.ulParameterLen = sizeof(rc2_params);	blockSize = 8;	break;#if NSS_SOFTOKEN_DOES_RC5    case CKM_RC5_MAC_GENERAL:	mac_bytes = 	    ((CK_RC5_MAC_GENERAL_PARAMS *)pMechanism->pParameter)->ulMacLength;	/* fall through */    case CKM_RC5_MAC:	/* this works because ulEffectiveBits is in the same place in both the	 * CK_RC5_MAC_GENERAL_PARAMS and CK_RC5_CBC_PARAMS */	rc5_mac = (CK_RC5_MAC_GENERAL_PARAMS *)pMechanism->pParameter;	rc5_params.ulWordsize = rc5_mac->ulWordsize;	rc5_params.ulRounds = rc5_mac->ulRounds;	rc5_params.pIv = ivBlock;	blockSize = rc5_mac->ulWordsize*2;	rc5_params.ulIvLen = blockSize;	PORT_Memset(ivBlock,0,blockSize);	cbc_mechanism.mechanism = CKM_RC5_CBC;	cbc_mechanism.pParameter = &rc5_params;	cbc_mechanism.ulParameterLen = sizeof(rc5_params);	break;#endif    /* add cast and idea later */    case CKM_DES_MAC_GENERAL:	mac_bytes = *(CK_ULONG *)pMechanism->pParameter;	/* fall through */    case CKM_DES_MAC:	blockSize = 8;	PORT_Memset(ivBlock,0,blockSize);	cbc_mechanism.mechanism = CKM_DES_CBC;	cbc_mechanism.pParameter = &ivBlock;	cbc_mechanism.ulParameterLen = blockSize;	break;    case CKM_DES3_MAC_GENERAL:	mac_bytes = *(CK_ULONG *)pMechanism->pParameter;	/* fall through */    case CKM_DES3_MAC:	blockSize = 8;	PORT_Memset(ivBlock,0,blockSize);	cbc_mechanism.mechanism = CKM_DES3_CBC;	cbc_mechanism.pParameter = &ivBlock;	cbc_mechanism.ulParameterLen = blockSize;	break;    case CKM_CDMF_MAC_GENERAL:	mac_bytes = *(CK_ULONG *)pMechanism->pParameter;	/* fall through */    case CKM_CDMF_MAC:	blockSize = 8;	PORT_Memset(ivBlock,0,blockSize);	cbc_mechanism.mechanism = CKM_CDMF_CBC;	cbc_mechanism.pParameter = &ivBlock;	cbc_mechanism.ulParameterLen = blockSize;	break;    default:	return CKR_FUNCTION_NOT_SUPPORTED;    }    crv = pk11_EncryptInit(hSession, &cbc_mechanism, hKey, keyUsage,								contextType);    if (crv != CKR_OK) return crv;    crv = pk11_GetContext(hSession,&context,contextType,PR_TRUE,NULL);    /* this shouldn't happen! */    PORT_Assert(crv == CKR_OK);    if (crv != CKR_OK) return crv;    context->blockSize = blockSize;    if (mac_bytes == PK11_INVALID_MAC_SIZE) mac_bytes = blockSize/2;    context->macSize = mac_bytes;    return CKR_OK;}/* * encode RSA PKCS #1 Signature data before signing...  */static SECStatuspk11_HashSign(PK11HashSignInfo *info,unsigned char *sig,unsigned int *sigLen,		unsigned int maxLen,unsigned char *hash, unsigned int hashLen){        SECStatus rv = SECFailure;    SECItem digder;    PLArenaPool *arena = NULL;    SGNDigestInfo *di = NULL;    digder.data = NULL;    arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);    if ( !arena ) { goto loser; }        /* Construct digest info */    di = SGN_CreateDigestInfo(info->hashOid, hash, hashLen);    if (!di) { goto loser; }    /* Der encode the digest as a DigestInfo */    rv = DER_Encode(arena, &digder, SGNDigestInfoTemplate, di);    if (rv != SECSuccess) {	goto loser;    }    /*    ** Encrypt signature after constructing appropriate PKCS#1 signature    ** block    */    rv = RSA_Sign(info->key,sig,sigLen,maxLen,digder.data,digder.len);  loser:    SGN_DestroyDigestInfo(di);    if (arena != NULL) {	PORT_FreeArena(arena, PR_FALSE);    }    return rv;}static SECStatusnsc_DSA_Verify_Stub(void *ctx, CK_BYTE_PTR pSignature, CK_ULONG ulSignatureLen,			    CK_BYTE_PTR pData, CK_ULONG ulDataLen){    SECItem signature, digest;    signature.data = pSignature;    signature.len = ulSignatureLen;    digest.data = pData;    digest.len = ulDataLen;    return DSA_VerifyDigest((DSAPublicKey *)ctx, &signature, &digest);}static SECStatusnsc_DSA_Sign_Stub(void *ctx, CK_BYTE_PTR pSignature,			    CK_ULONG_PTR ulSignatureLen, CK_ULONG maxulSignatureLen,			    CK_BYTE_PTR pData, CK_ULONG ulDataLen){    SECItem signature = { 0 }, digest;    SECStatus rv;    (void)SECITEM_AllocItem(NULL, &signature, maxulSignatureLen);    digest.data = pData;    digest.len = ulDataLen;    rv = DSA_SignDigest((DSAPrivateKey *)ctx, &signature, &digest);    *ulSignatureLen = signature.len;    PORT_Memcpy(pSignature, signature.data, signature.len);    SECITEM_FreeItem(&signature, PR_FALSE);    return rv;}/* NSC_SignInit setups up the signing operations. There are three basic * types of signing: *	(1) the tradition single part, where "Raw RSA" or "Raw DSA" is applied *  to data in a single Sign operation (which often looks a lot like an *  encrypt, with data coming in and data going out). *	(2) Hash based signing, where we continually hash the data, then apply *  some sort of signature to the end. *	(3) Block Encryption CBC MAC's, where the Data is encrypted with a key, *  and only the final block is part of the mac. * *  For case number 3, we initialize a context much like the Encryption Context *  (in fact we share code). We detect case 3 in C_SignUpdate, C_Sign, and  *  C_Final by the following method... if it's not multi-part, and it's doesn't *  have a hash context, it must be a block Encryption CBC MAC. * *  For case number 2, we initialize a hash structure, as well as make it  *  multi-part. Updates are simple calls to the hash update function. Final *  calls the hashend, then passes the result to the 'update' function (which *  operates as a final signature function). In some hash based MAC'ing (as *  opposed to hash base signatures), the update function is can be simply a  *  copy (as is the case with HMAC). */CK_RV NSC_SignInit(CK_SESSION_HANDLE hSession,		 CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey){    PK11Session *session;    PK11Object *key;    PK11SessionContext *context;    CK_KEY_TYPE key_type;    CK_RV crv = CKR_OK;    SECKEYLowPrivateKey *privKey;    PK11HashSignInfo *info = NULL;    /* Block Cipher MACing Algorithms use a different Context init method..*/    crv = pk11_InitCBCMac(hSession, pMechanism, hKey, CKA_SIGN, PK11_SIGN);    if (crv != CKR_FUNCTION_NOT_SUPPORTED) return crv;    /* we're not using a block cipher mac */    session = pk11_SessionFromHandle(hSession);    if (session == NULL) return CKR_SESSION_HANDLE_INVALID;    crv = pk11_InitGeneric(session,&context,PK11_SIGN,&key,hKey,&key_type,						CKO_PRIVATE_KEY,CKA_SIGN);    if (crv != CKR_OK) {	pk11_FreeSession(session);	return crv;    }    context->multi = PR_FALSE;    switch(pMechanism->mechanism) {    case CKM_MD5_RSA_PKCS:        context->multi = PR_TRUE;	crv = pk11_doSubMD2(context);	if (crv != CKR_OK) break;	context->update = (PK11Cipher) pk11_HashSign;	info = (PK11HashSignInfo *)PORT_Alloc(sizeof(PK11HashSignInfo));	if (info == NULL) {	   crv = CKR_HOST_MEMORY;	   break;	}	info->hashOid = SEC_OID_MD5;	goto finish_rsa;    case CKM_MD2_RSA_PKCS:        context->multi = PR_TRUE;	crv = pk11_doSubMD2(context);	if (crv != CKR_OK) break;	context->update = (PK11Cipher) pk11_HashSign;	info = (PK11HashSignInfo *)PORT_Alloc(sizeof(PK11HashSignInfo));	if (info == NULL) {	   crv = CKR_HOST_MEMORY;	   break;	}	info->hashOid = SEC_OID_MD2;	goto finish_rsa;    case CKM_SHA1_RSA_PKCS:        context->multi = PR_TRUE;	crv = pk11_doSubSHA1(context);	if (crv != CKR_OK) break;	context->update = (PK11Cipher) pk11_HashSign;	info = (PK11HashSignInfo *)PORT_Alloc(sizeof(PK11HashSignInfo));	if (info == NULL) {	   crv = CKR_HOST_MEMORY;	   break;	}	info->hashOid = SEC_OID_SHA1;	goto finish_rsa;    case CKM_RSA_PKCS:	context->update = (PK11Cipher) RSA_Sign;	goto finish_rsa;    case CKM_RSA_X_509:	context->update = (PK11Cipher)  RSA_SignRaw;finish_rsa:	if (key_type != CKK_RSA) {	    if (info) PORT_Free(info);	    crv = CKR_KEY_TYPE_INCONSISTENT;	    break;	}	context->multi = PR_FALSE;	privKey = pk11_GetPrivKey(key,CKK_RSA);	if (privKey == NULL) {	    if (info) PORT_Free(info);	    crv = CKR_HOST_MEMORY;	    break;	}	/* OK, info is allocated only if we're doing hash and sign mechanism.	 * It's necessary to be able to set the correct OID in the final 	 * signature.	 * Second, what's special about privKey == key->objectInfo?	 * Well we don't 'cache' token versions	 * of private keys because (1) it's sensitive data, and (2) it never	 * gets destroyed. Instead we grab the key out of the database as	 * necessary, but now the key is our context, and we need to free	 * it when we are done. Non-token private keys will get freed when	 * the user destroys the session object (or the session the session	 * object lives in) */	if (info) {	    info->key = privKey;	    context->cipherInfo = info;	    context->destroy = (privKey == key->objectInfo) ?		(PK11Destroy)pk11_Space:(PK11Destroy)pk11_FreeSignInfo;	} else {	    context->cipherInfo = privKey;	    context->destroy = (privKey == key->objectInfo) ?		(PK11Destroy)pk11_Null:(PK11Destroy)pk11_FreePrivKey;	}	break;    case CKM_DSA_SHA1:        context->multi = PR_TRUE;	crv = pk11_doSubSHA1(context);	if (crv != CKR_OK) break;	/* fall through */    case CKM_DSA:	if (key_type != CKK_DSA) {	    crv = CKR_KEY_TYPE_INCONSISTENT;	    break;	}	privKey = pk11_GetPrivKey(key,CKK_DSA);	if (privKey == NULL) {	    crv = CKR_HOST_MEMORY;	    break;	}	context->cipherInfo = &(privKey->u.dsa);	context->update     = (PK11Cipher) nsc_DSA_Sign_Stub;	context->destroy    = pk11_Null;        if (key->objectInfo != privKey) SECKEY_LowDestroyPrivateKey(privKey);	break;    case CKM_MD2_HMAC_GENERAL:	crv = pk11_doHMACInit(context,SEC_OID_MD2,key,				*(CK_ULONG *)pMechanism->pParameter);	break;    case CKM_MD2_HMAC:	crv = pk11_doHMACInit(context,SEC_OID_MD2,key,MD2_LENGTH);	break;    case CKM_MD5_HMAC_GENERAL:	crv = pk11_doHMACInit(context,SEC_OID_MD5,key,				*(CK_ULONG *)pMechanism->pParameter);	break;    case CKM_MD5_HMAC:	crv = pk11_doHMACInit(context,SEC_OID_MD5,key,MD5_LENGTH);	break;    case CKM_SHA_1_HMAC_GENERAL:	crv = pk11_doHMACInit(context,SEC_OID_SHA1,key,				*(CK_ULONG *)pMechanism->pParameter);	break;    case CKM_SHA_1_HMAC:	crv = pk11_doHMACInit(context,SEC_OID_SHA1,key,SHA1_LENGTH);	break;    case CKM_SSL3_MD5_MAC:	crv = pk11_doSSLMACInit(context,SEC_OID_MD5,key,					*(CK_ULONG *)pMechanism->pParameter);	break;    case CKM_SSL3_SHA1_MAC:	crv = pk11_doSSLMACInit(context,SEC_OID_SHA1,key,					*(CK_ULONG *)pMechanism->pParameter);	break;    case CKM_TLS_PRF_GENERAL:	crv = pk11_TLSPRFInit(context, key, key_type);	break;    default:	crv = CKR_MECHANISM_INVALID;	break;    }    pk11_FreeObject(key);    if (crv != CKR_OK) {        PORT_Free(context);	pk11_FreeSession(session);	return crv;    }    pk11_SetContextByType(session, PK11_SIGN, context);    pk11_FreeSession(session);    return CKR_OK;}/* MACUpdate is the common implementation for SignUpdate and VerifyUpdate. * (sign and verify only very in their setup and final operations) */static CK_RV pk11_MACUpdate(CK_SESSION_HANDLE hSession,CK_BYTE_PTR pPart,    					CK_ULONG ulPartLen,PK11ContextType type){    unsigned int outlen;    PK11SessionContext *context;    CK_RV crv;    SECStatus rv;    /* make sure we're legal */    crv = pk11_GetContext(hSession,&context,type,PR_FALSE,NULL);    if (crv != CKR_OK) return crv;    if (context->hashInfo) {	(*context->hashUpdate)(context->hashInfo, pPart, ulPartLen);	return CKR_OK;    }    /* must be block cipher macing */    /* deal with previous buffered data */    if (context->padDataLength != 0) {	int i;	/* fill in the padded to a full block size */	for (i=context->padDataLength; (ulPartLen != 0) && 					i < (int)context->blockSize; i++) {	    context->padBuf[i] = *pPart++;	    ulPartLen--;	    context->padDataLength++;	}	/* not enough data to encrypt yet? then return */	if (context->padDataLength != context->blockSize)  return CKR_OK;	/* encrypt the current padded data */    	rv = (*context->update)(context->cipherInfo,context->macBuf,&outlen,			PK11_MAX_BLOCK_SIZE,context->padBuf,context->blockSize);    	if (rv != SECSuccess) return CKR_DEVICE_ERROR;    }    /* save the residual */    context->padDataLength = ulPartLen % context->blockSize;    if (co

⌨️ 快捷键说明

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