pkcs11c.c

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

C
2,203
字号
    return CKR_OK;}/* ************** Crypto Functions:     Encrypt ************************ *//* * All the NSC_InitXXX functions have a set of common checks and processing they * all need to do at the beginning. This is done here. */static CK_RVpk11_InitGeneric(PK11Session *session,PK11SessionContext **contextPtr,		 PK11ContextType ctype,PK11Object **keyPtr,		 CK_OBJECT_HANDLE hKey, CK_KEY_TYPE *keyTypePtr,		 CK_OBJECT_CLASS pubKeyType, CK_ATTRIBUTE_TYPE operation){    PK11Object *key = NULL;    PK11Attribute *att;    PK11SessionContext *context;    /* We can only init if there is not current context active */    if (pk11_ReturnContextByType(session,ctype) != NULL) {	return CKR_OPERATION_ACTIVE;    }    /* find the key */    if (keyPtr) {        key = pk11_ObjectFromHandle(hKey,session);        if (key == NULL) {	    return CKR_KEY_HANDLE_INVALID;    	}	/* make sure it's a valid  key for this operation */	if (((key->objclass != CKO_SECRET_KEY) && (key->objclass != pubKeyType))					|| !pk11_isTrue(key,operation)) {	    pk11_FreeObject(key);	    return CKR_KEY_TYPE_INCONSISTENT;	}	/* get the key type */	att = pk11_FindAttribute(key,CKA_KEY_TYPE);	PORT_Assert(att != NULL);	*keyTypePtr = *(CK_KEY_TYPE *)att->attrib.pValue;	pk11_FreeAttribute(att);	*keyPtr = key;    }    /* allocate the context structure */    context = (PK11SessionContext *)PORT_Alloc(sizeof(PK11SessionContext));    if (context == NULL) {	if (key) pk11_FreeObject(key);	return CKR_HOST_MEMORY;    }    context->type = ctype;    context->multi = PR_TRUE;    context->cipherInfo = NULL;    context->hashInfo = NULL;    context->doPad = PR_FALSE;    context->padDataLength = 0;    *contextPtr = context;    return CKR_OK;}/* NSC_EncryptInit initializes an encryption operation. *//* This function is used by NSC_EncryptInit and NSC_WrapKey. The only difference * in their uses if whether or not etype is CKA_ENCRYPT or CKA_WRAP */static CK_RVpk11_EncryptInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism,		 CK_OBJECT_HANDLE hKey, CK_ATTRIBUTE_TYPE etype,		 PK11ContextType contextType){    PK11Session *session;    PK11Object *key;    PK11SessionContext *context;    PK11Attribute *att;    CK_RC2_CBC_PARAMS *rc2_param;#if NSS_SOFTOKEN_DOES_RC5    CK_RC5_CBC_PARAMS *rc5_param;    SECItem rc5Key;#endif    CK_KEY_TYPE key_type;    CK_RV crv = CKR_OK;    SECKEYLowPublicKey *pubKey;    unsigned effectiveKeyLength;    unsigned char newdeskey[8];    PRBool useNewKey=PR_FALSE;    int t;    session = pk11_SessionFromHandle(hSession);    if (session == NULL) return CKR_SESSION_HANDLE_INVALID;    crv = pk11_InitGeneric(session,&context,contextType,&key,hKey,&key_type,    						CKO_PUBLIC_KEY, etype);						    if (crv != CKR_OK) {	pk11_FreeSession(session);	return crv;    }    context->doPad = PR_FALSE;    switch(pMechanism->mechanism) {    case CKM_RSA_PKCS:    case CKM_RSA_X_509:	if (key_type != CKK_RSA) {	    crv = CKR_KEY_TYPE_INCONSISTENT;	    break;	}	context->multi = PR_FALSE;	pubKey = pk11_GetPubKey(key,CKK_RSA);	if (pubKey == NULL) {	    crv = CKR_HOST_MEMORY;	    break;	}	context->cipherInfo = pubKey;	context->update = (PK11Cipher) (pMechanism->mechanism == CKM_RSA_X_509			? RSA_EncryptRaw : RSA_EncryptBlock);	context->destroy = pk11_Null;	break;    case CKM_RC2_CBC_PAD:	context->doPad = PR_TRUE;	context->blockSize = 8;	/* fall thru */    case CKM_RC2_ECB:    case CKM_RC2_CBC:	if (key_type != CKK_RC2) {	    crv = CKR_KEY_TYPE_INCONSISTENT;	    break;	}	att = pk11_FindAttribute(key,CKA_VALUE);	if (att == NULL) {	    crv = CKR_KEY_HANDLE_INVALID;	    break;	}	rc2_param = (CK_RC2_CBC_PARAMS *)pMechanism->pParameter;	effectiveKeyLength = (rc2_param->ulEffectiveBits+7)/8;	context->cipherInfo = 	    RC2_CreateContext((unsigned char*)att->attrib.pValue,			      att->attrib.ulValueLen, rc2_param->iv,			      pMechanism->mechanism == CKM_RC2_ECB ? NSS_RC2 :			      NSS_RC2_CBC,effectiveKeyLength);	pk11_FreeAttribute(att);	if (context->cipherInfo == NULL) {	    crv = CKR_HOST_MEMORY;	    break;	}	context->update = (PK11Cipher) RC2_Encrypt;	context->destroy = (PK11Destroy) RC2_DestroyContext;	break;#if NSS_SOFTOKEN_DOES_RC5    case CKM_RC5_CBC_PAD:	context->doPad = PR_TRUE;	/* fall thru */    case CKM_RC5_ECB:    case CKM_RC5_CBC:	if (key_type != CKK_RC5) {	    crv = CKR_KEY_TYPE_INCONSISTENT;	    break;	}	att = pk11_FindAttribute(key,CKA_VALUE);	if (att == NULL) {	    crv = CKR_KEY_HANDLE_INVALID;	    break;	}	rc5_param = (CK_RC5_CBC_PARAMS *)pMechanism->pParameter;	if (context->doPad) {	   context->blockSize = rc5_param->ulWordsize*2;	}	rc5Key.data = (unsigned char*)att->attrib.pValue;	rc5Key.len = att->attrib.ulValueLen;	context->cipherInfo = RC5_CreateContext(&rc5Key,rc5_param->ulRounds,	   rc5_param->ulWordsize,rc5_param->pIv,		 pMechanism->mechanism == CKM_RC5_ECB ? NSS_RC5 : NSS_RC5_CBC);	pk11_FreeAttribute(att);	if (context->cipherInfo == NULL) {	    crv = CKR_HOST_MEMORY;	    break;	}	context->update = (PK11Cipher) RC5_Encrypt;	context->destroy = (PK11Destroy) RC5_DestroyContext;	break;#endif    case CKM_RC4:	if (key_type != CKK_RC4) {	    crv = CKR_KEY_TYPE_INCONSISTENT;	    break;	}	att = pk11_FindAttribute(key,CKA_VALUE);	if (att == NULL) {	    crv = CKR_KEY_HANDLE_INVALID;	    break;	}	context->cipherInfo = 	    RC4_CreateContext((unsigned char*)att->attrib.pValue,			      att->attrib.ulValueLen);	pk11_FreeAttribute(att);	if (context->cipherInfo == NULL) {	    crv = CKR_HOST_MEMORY;  /* WRONG !!! */	    break;	}	context->update = (PK11Cipher) RC4_Encrypt;	context->destroy = (PK11Destroy) RC4_DestroyContext;	break;    case CKM_CDMF_CBC_PAD:	context->doPad = PR_TRUE;	context->blockSize = 8;	/* fall thru */    case CKM_CDMF_ECB:    case CKM_CDMF_CBC:	if (key_type != CKK_CDMF) {	    crv = CKR_KEY_TYPE_INCONSISTENT;	    break;	}	t = (pMechanism->mechanism == CKM_CDMF_ECB) ? NSS_DES : NSS_DES_CBC;	useNewKey=PR_TRUE;	if (crv != CKR_OK) break;	goto finish_des;    case CKM_DES_ECB:	if (key_type != CKK_DES) {	    crv = CKR_KEY_TYPE_INCONSISTENT;	    break;	}	t = NSS_DES;	goto finish_des;    case CKM_DES_CBC_PAD:	context->doPad = PR_TRUE;	context->blockSize = 8;	/* fall thru */    case CKM_DES_CBC:	if (key_type != CKK_DES) {	    crv = CKR_KEY_TYPE_INCONSISTENT;	    break;	}	t = NSS_DES_CBC;	goto finish_des;    case CKM_DES3_ECB:	if ((key_type != CKK_DES2) && (key_type != CKK_DES3)) {	    crv = CKR_KEY_TYPE_INCONSISTENT;	    break;	}	t = NSS_DES_EDE3;	goto finish_des;    case CKM_DES3_CBC_PAD:	context->doPad = PR_TRUE;	context->blockSize = 8;	/* fall thru */    case CKM_DES3_CBC:	if ((key_type != CKK_DES2) && (key_type != CKK_DES3)) {	    crv = CKR_KEY_TYPE_INCONSISTENT;	    break;	}	t = NSS_DES_EDE3_CBC;finish_des:	att = pk11_FindAttribute(key,CKA_VALUE);	if (att == NULL) {	    crv = CKR_KEY_HANDLE_INVALID;	    break;	}	if (useNewKey) {	    crv = pk11_cdmf2des((unsigned char*)att->attrib.pValue,newdeskey);	    if (crv != CKR_OK) {		pk11_FreeAttribute(att);		break;	     }	}	context->cipherInfo = DES_CreateContext(		useNewKey ? newdeskey : (unsigned char*)att->attrib.pValue,		(unsigned char*)pMechanism->pParameter,t, PR_TRUE);	pk11_FreeAttribute(att);	if (context->cipherInfo == NULL) {	    crv = CKR_HOST_MEMORY;	    break;	}	context->update = (PK11Cipher) DES_Encrypt;	context->destroy = (PK11Destroy) DES_DestroyContext;	break;    default:	crv = CKR_MECHANISM_INVALID;	break;    }    pk11_FreeObject(key);    if (crv != CKR_OK) {        pk11_FreeContext(context);	pk11_FreeSession(session);	return crv;    }    pk11_SetContextByType(session, contextType, context);    pk11_FreeSession(session);    return CKR_OK;}/* NSC_EncryptInit initializes an encryption operation. */CK_RV NSC_EncryptInit(CK_SESSION_HANDLE hSession,		 CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey){    return pk11_EncryptInit(hSession, pMechanism, hKey, CKA_ENCRYPT, 							PK11_ENCRYPT);}/* NSC_EncryptUpdate continues a multiple-part encryption operation. */CK_RV NSC_EncryptUpdate(CK_SESSION_HANDLE hSession,    CK_BYTE_PTR pPart, CK_ULONG ulPartLen, CK_BYTE_PTR pEncryptedPart,						CK_ULONG_PTR pulEncryptedPartLen){    PK11SessionContext *context;    unsigned int outlen,i;    unsigned int padoutlen = 0;    unsigned int maxout = *pulEncryptedPartLen;    CK_RV crv;    SECStatus rv;    /* make sure we're legal */    crv = pk11_GetContext(hSession,&context,PK11_ENCRYPT,PR_TRUE,NULL);    if (crv != CKR_OK) return crv;    /* do padding */    if (context->doPad) {	/* deal with previous buffered data */	if (context->padDataLength != 0) {	    /* fill in the padded to a full block size */	    for (i=context->padDataLength; 			(ulPartLen != 0) && i < context->blockSize; i++) {		context->padBuf[i] = *pPart++;		ulPartLen--;		context->padDataLength++;	    }	    /* not enough data to encrypt yet? then return */	    if (context->padDataLength != context->blockSize) {		*pulEncryptedPartLen = 0;		return CKR_OK;	    }	    /* encrypt the current padded data */    	    rv = (*context->update)(context->cipherInfo,pEncryptedPart, 		&outlen,context->blockSize,context->padBuf,context->blockSize);    	    if (rv != SECSuccess) return CKR_DEVICE_ERROR;	    pEncryptedPart += padoutlen;	    maxout -= padoutlen;	}	/* save the residual */	context->padDataLength = ulPartLen % context->blockSize;	if (context->padDataLength) {	    PORT_Memcpy(context->padBuf,			&pPart[ulPartLen-context->padDataLength],							context->padDataLength);	    ulPartLen -= context->padDataLength;	}	/* if we've exhausted our new buffer, we're done */	if (ulPartLen == 0) {	    *pulEncryptedPartLen = padoutlen;	    return CKR_OK;	}    }	    /* do it: NOTE: this assumes buf size in is >= buf size out! */    rv = (*context->update)(context->cipherInfo,pEncryptedPart, 					&outlen, maxout, pPart, ulPartLen);    *pulEncryptedPartLen = (CK_ULONG) (outlen + padoutlen);    return (rv == SECSuccess) ? CKR_OK : CKR_DEVICE_ERROR;}/* NSC_EncryptFinal finishes a multiple-part encryption operation. */CK_RV NSC_EncryptFinal(CK_SESSION_HANDLE hSession,    CK_BYTE_PTR pLastEncryptedPart, CK_ULONG_PTR pulLastEncryptedPartLen){    PK11Session *session;    PK11SessionContext *context;    unsigned int outlen,i;    unsigned int maxout = *pulLastEncryptedPartLen;    CK_RV crv;    SECStatus rv = SECSuccess;    /* make sure we're legal */    crv = pk11_GetContext(hSession,&context,PK11_ENCRYPT,PR_TRUE,&session);    if (crv != CKR_OK) return crv;    *pulLastEncryptedPartLen = 0;    /* do padding */    if (context->doPad) {	unsigned char  padbyte = (unsigned char) 				(context->blockSize - context->padDataLength); 	/* fill out rest of pad buffer with pad magic*/	for (i=context->padDataLength; i < context->blockSize; i++) {	    context->padBuf[i] = padbyte;	}	rv = (*context->update)(context->cipherInfo,pLastEncryptedPart, 			&outlen, maxout, context->padBuf, context->blockSize);	if (rv == SECSuccess) *pulLastEncryptedPartLen = (CK_ULONG) outlen;    }    /* do it */    pk11_SetContextByType(session, PK11_ENCRYPT, NULL);    pk11_FreeContext(context);    pk11_FreeSession(session);    return (rv == SECSuccess) ? CKR_OK : CKR_DEVICE_ERROR;}/* NSC_Encrypt encrypts single-part data. */CK_RV NSC_Encrypt (CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData,    		CK_ULONG ulDataLen, CK_BYTE_PTR pEncryptedData,					 CK_ULONG_PTR pulEncryptedDataLen){    PK11Session *session;    PK11SessionContext *context;    unsigned int outlen;    unsigned int maxoutlen = *pulEncryptedDataLen;    CK_RV crv;    CK_RV crv2;    SECStatus rv;    /* make sure we're legal */    crv = pk11_GetContext(hSession,&context,PK11_ENCRYPT,PR_FALSE,&session);    if (crv != CKR_OK) return crv;    if (context->doPad) {	CK_ULONG finalLen;	/* padding is fairly complicated, have the update and final 	 * code deal with it */        pk11_FreeSession(session);	crv = NSC_EncryptUpdate(hSession,pData,ulDataLen,pEncryptedData,							pulEncryptedDataLen);	if (crv != CKR_OK) *pulEncryptedDataLen = 0;	maxoutlen -= *pulEncryptedDataLen;	pEncryptedData += *pulEncryptedDataLen;	finalLen = maxoutlen;	crv2 = NSC_EncryptFinal(hSession, pEncryptedData, &finalLen);	if (crv2 == CKR_OK) { *pulEncryptedDataLen += finalLen; }	return crv == CKR_OK ? crv2 :crv;    }	    /* do it: NOTE: this assumes buf size is big enough. */    rv = (*context->update)(context->cipherInfo, pEncryptedData, 					&outlen, maxoutlen, pData, ulDataLen);    *pulEncryptedDataLen = (CK_ULONG) outlen;

⌨️ 快捷键说明

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