bug 150704, PK11_Finalize can crash because softoken does not implement C_XXXFinal correctly

This commit is contained in:
ian.mcgreer%sun.com 2002-06-19 14:59:24 +00:00
Родитель fb0381c091
Коммит 41ebe0592b
2 изменённых файлов: 100 добавлений и 17 удалений

Просмотреть файл

@ -4020,31 +4020,34 @@ pk11_Finalize(PK11Context *context)
{
CK_ULONG count = 0;
CK_RV crv;
unsigned char stackBuf[256];
unsigned char *buffer = NULL;
if (!context->ownSession) {
return SECSuccess;
}
finalize:
switch (context->operation) {
case CKA_ENCRYPT:
crv=PK11_GETTAB(context->slot)->C_EncryptFinal(context->session,
NULL,&count);
buffer, &count);
break;
case CKA_DECRYPT:
crv = PK11_GETTAB(context->slot)->C_DecryptFinal(context->session,
NULL,&count);
buffer, &count);
break;
case CKA_SIGN:
crv=PK11_GETTAB(context->slot)->C_SignFinal(context->session,
NULL,&count);
buffer, &count);
break;
case CKA_VERIFY:
crv=PK11_GETTAB(context->slot)->C_VerifyFinal(context->session,
NULL,count);
buffer, count);
break;
case CKA_DIGEST:
crv=PK11_GETTAB(context->slot)->C_DigestFinal(context->session,
NULL,&count);
buffer, &count);
break;
default:
crv = CKR_OPERATION_NOT_INITIALIZED;
@ -4052,9 +4055,23 @@ pk11_Finalize(PK11Context *context)
}
if (crv != CKR_OK) {
if (crv == CKR_OPERATION_NOT_INITIALIZED) {
/* if there's no operation, it is finalized */
return SECSuccess;
}
PORT_SetError( PK11_MapError(crv) );
return SECFailure;
}
/* try to finalize the session with a buffer */
if (buffer == NULL && count > 0) {
if (count < sizeof stackBuf) {
buffer = stackBuf;
goto finalize;
} else {
return SECFailure;
}
}
return SECSuccess;
}

Просмотреть файл

@ -443,6 +443,7 @@ pk11_InitGeneric(PK11Session *session,PK11SessionContext **contextPtr,
context->doPad = PR_FALSE;
context->padDataLength = 0;
context->key = key;
context->blockSize = 0;
*contextPtr = context;
return CKR_OK;
@ -795,12 +796,21 @@ CK_RV NSC_EncryptFinal(CK_SESSION_HANDLE hSession,
unsigned int maxout = *pulLastEncryptedPartLen;
CK_RV crv;
SECStatus rv = SECSuccess;
PRBool contextFinished = PR_TRUE;
/* make sure we're legal */
crv = pk11_GetContext(hSession,&context,PK11_ENCRYPT,PR_TRUE,&session);
if (crv != CKR_OK) return crv;
*pulLastEncryptedPartLen = 0;
if (!pLastEncryptedPart) {
/* caller is checking the amount of remaining data */
if (context->blockSize > 0) {
*pulLastEncryptedPartLen = context->blockSize;
contextFinished = PR_FALSE; /* still have padding to go */
}
goto finish;
}
/* do padding */
if (context->doPad) {
@ -815,9 +825,11 @@ CK_RV NSC_EncryptFinal(CK_SESSION_HANDLE hSession,
if (rv == SECSuccess) *pulLastEncryptedPartLen = (CK_ULONG) outlen;
}
/* do it */
finish:
if (contextFinished) {
pk11_SetContextByType(session, PK11_ENCRYPT, NULL);
pk11_FreeContext(context);
}
pk11_FreeSession(session);
return (rv == SECSuccess) ? CKR_OK : CKR_DEVICE_ERROR;
}
@ -839,6 +851,11 @@ CK_RV NSC_Encrypt (CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData,
crv = pk11_GetContext(hSession,&context,PK11_ENCRYPT,PR_FALSE,&session);
if (crv != CKR_OK) return crv;
if (!pEncryptedData) {
*pulEncryptedDataLen = ulDataLen + 2 * context->blockSize;
goto finish;
}
if (context->doPad) {
CK_ULONG finalLen;
/* padding is fairly complicated, have the update and final
@ -860,8 +877,9 @@ CK_RV NSC_Encrypt (CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData,
rv = (*context->update)(context->cipherInfo, pEncryptedData,
&outlen, maxoutlen, pData, ulDataLen);
*pulEncryptedDataLen = (CK_ULONG) outlen;
pk11_FreeContext(context);
pk11_SetContextByType(session, PK11_ENCRYPT, NULL);
pk11_FreeContext(context);
finish:
pk11_FreeSession(session);
return (rv == SECSuccess) ? CKR_OK : CKR_DEVICE_ERROR;
@ -930,12 +948,22 @@ CK_RV NSC_DecryptFinal(CK_SESSION_HANDLE hSession,
unsigned int maxout = *pulLastPartLen;
CK_RV crv;
SECStatus rv = SECSuccess;
PRBool contextFinished = PR_TRUE;
/* make sure we're legal */
crv = pk11_GetContext(hSession,&context,PK11_DECRYPT,PR_TRUE,&session);
if (crv != CKR_OK) return crv;
*pulLastPartLen = 0;
if (!pLastPart) {
/* caller is checking the amount of remaining data */
if (context->padDataLength > 0) {
*pulLastPartLen = 2 * context->blockSize;
contextFinished = PR_FALSE; /* still have padding to go */
}
goto finish;
}
if (context->doPad) {
/* decrypt our saved buffer */
if (context->padDataLength != 0) {
@ -955,9 +983,11 @@ CK_RV NSC_DecryptFinal(CK_SESSION_HANDLE hSession,
}
}
/* do it */
finish:
if (contextFinished) {
pk11_SetContextByType(session, PK11_DECRYPT, NULL);
pk11_FreeContext(context);
}
pk11_FreeSession(session);
return (rv == SECSuccess) ? CKR_OK : CKR_DEVICE_ERROR;
}
@ -979,6 +1009,11 @@ CK_RV NSC_Decrypt(CK_SESSION_HANDLE hSession,
crv = pk11_GetContext(hSession,&context,PK11_DECRYPT,PR_FALSE,&session);
if (crv != CKR_OK) return crv;
if (!pData) {
*pulDataLen = ulEncryptedDataLen + context->blockSize;
goto finish;
}
if (context->doPad) {
CK_ULONG finalLen;
/* padding is fairly complicated, have the update and final
@ -998,8 +1033,9 @@ CK_RV NSC_Decrypt(CK_SESSION_HANDLE hSession,
rv = (*context->update)(context->cipherInfo, pData, &outlen, maxoutlen,
pEncryptedData, ulEncryptedDataLen);
*pulDataLen = (CK_ULONG) outlen;
pk11_FreeContext(context);
pk11_SetContextByType(session, PK11_DECRYPT, NULL);
pk11_FreeContext(context);
finish:
pk11_FreeSession(session);
return (rv == SECSuccess) ? CKR_OK : CKR_DEVICE_ERROR;
}
@ -1042,6 +1078,7 @@ CK_RV NSC_DigestInit(CK_SESSION_HANDLE hSession,
context->hashUpdate = (PK11Hash) MD2_Update;
context->end = (PK11End) MD2_End;
context->destroy = (PK11Destroy) MD2_DestroyContext;
context->maxLen = MD2_LENGTH;
MD2_Begin(md2_context);
break;
case CKM_MD5:
@ -1056,6 +1093,7 @@ CK_RV NSC_DigestInit(CK_SESSION_HANDLE hSession,
context->hashUpdate = (PK11Hash) MD5_Update;
context->end = (PK11End) MD5_End;
context->destroy = (PK11Destroy) MD5_DestroyContext;
context->maxLen = MD5_LENGTH;
MD5_Begin(md5_context);
break;
case CKM_SHA_1:
@ -1071,6 +1109,7 @@ CK_RV NSC_DigestInit(CK_SESSION_HANDLE hSession,
context->end = (PK11End) SHA1_End;
context->destroy = (PK11Destroy) SHA1_DestroyContext;
SHA1_Begin(sha1_context);
context->maxLen = SHA1_LENGTH;
break;
default:
crv = CKR_MECHANISM_INVALID;
@ -1103,6 +1142,11 @@ CK_RV NSC_Digest(CK_SESSION_HANDLE hSession,
crv = pk11_GetContext(hSession,&context,PK11_HASH,PR_FALSE,&session);
if (crv != CKR_OK) return crv;
if (pDigest == NULL) {
*pulDigestLen = context->maxLen;
goto finish;
}
/* do it: */
(*context->hashUpdate)(context->cipherInfo, pData, ulDataLen);
/* NOTE: this assumes buf size is bigenough for the algorithm */
@ -1111,6 +1155,7 @@ CK_RV NSC_Digest(CK_SESSION_HANDLE hSession,
pk11_SetContextByType(session, PK11_HASH, NULL);
pk11_FreeContext(context);
finish:
pk11_FreeSession(session);
return CKR_OK;
}
@ -1149,12 +1194,12 @@ CK_RV NSC_DigestFinal(CK_SESSION_HANDLE hSession,CK_BYTE_PTR pDigest,
if (pDigest != NULL) {
(*context->end)(context->cipherInfo, pDigest, &digestLen, maxout);
*pulDigestLen = digestLen;
} else {
*pulDigestLen = 0;
}
pk11_SetContextByType(session, PK11_HASH, NULL);
pk11_FreeContext(context);
} else {
*pulDigestLen = context->maxLen;
}
pk11_FreeSession(session);
return CKR_OK;
}
@ -1264,6 +1309,7 @@ pk11_doHMACInit(PK11SessionContext *context,HASH_HashType hash,
context->destroy = (PK11Destroy) pk11_Space;
context->update = (PK11Cipher) pk11_HMACCopy;
context->verify = (PK11Verify) pk11_HMACCmp;
context->maxLen = hashObj->length;
HMAC_Begin(HMACcontext);
return CKR_OK;
}
@ -1384,6 +1430,7 @@ pk11_doSSLMACInit(PK11SessionContext *context,SECOidTag oid,
context->destroy = (PK11Destroy) pk11_Space;
context->update = (PK11Cipher) pk11_SSLMACSign;
context->verify = (PK11Verify) pk11_SSLMACVerify;
context->maxLen = mac_size;
return CKR_OK;
}
@ -1855,6 +1902,7 @@ finish_rsa:
context->cipherInfo = privKey;
context->destroy = (PK11Destroy)pk11_Null;
}
context->maxLen = nsslowkey_PrivateModulusLen(privKey);
break;
case CKM_DSA_SHA1:
@ -1876,6 +1924,7 @@ finish_rsa:
context->update = (PK11Cipher) nsc_DSA_Sign_Stub;
context->destroy = (privKey == key->objectInfo) ?
(PK11Destroy) pk11_Null:(PK11Destroy)pk11_FreePrivKey;
context->maxLen = DSA_SIGNATURE_LEN;
break;
case CKM_MD2_HMAC_GENERAL:
@ -2023,7 +2072,10 @@ CK_RV NSC_SignFinal(CK_SESSION_HANDLE hSession,CK_BYTE_PTR pSignature,
crv = pk11_GetContext(hSession,&context,PK11_SIGN,PR_TRUE,&session);
if (crv != CKR_OK) return crv;
if (context->hashInfo) {
if (!pSignature) {
*pulSignatureLen = context->maxLen;
goto finish;
} else if (context->hashInfo) {
(*context->end)(context->hashInfo, tmpbuf, &digestLen, sizeof(tmpbuf));
rv = (*context->update)(context->cipherInfo, pSignature,
&outlen, maxoutlen, tmpbuf, digestLen);
@ -2047,6 +2099,8 @@ CK_RV NSC_SignFinal(CK_SESSION_HANDLE hSession,CK_BYTE_PTR pSignature,
pk11_FreeContext(context);
pk11_SetContextByType(session, PK11_SIGN, NULL);
finish:
pk11_FreeSession(session);
return (rv == SECSuccess) ? CKR_OK : CKR_DEVICE_ERROR;
@ -2070,6 +2124,11 @@ CK_RV NSC_Sign(CK_SESSION_HANDLE hSession,
crv = pk11_GetContext(hSession,&context,PK11_SIGN,PR_FALSE,&session);
if (crv != CKR_OK) return crv;
if (!pSignature) {
*pulSignatureLen = context->maxLen;
goto finish;
}
/* multi part Signing are completely implemented by SignUpdate and
* sign Final */
if (context->multi) {
@ -2085,6 +2144,8 @@ CK_RV NSC_Sign(CK_SESSION_HANDLE hSession,
*pulSignatureLen = (CK_ULONG) outlen;
pk11_FreeContext(context);
pk11_SetContextByType(session, PK11_SIGN, NULL);
finish:
pk11_FreeSession(session);
return (rv == SECSuccess) ? CKR_OK : CKR_DEVICE_ERROR;
@ -5095,6 +5156,7 @@ CK_RV NSC_GetOperationState(CK_SESSION_HANDLE hSession,
PK11SessionContext *context;
PK11Session *session;
CK_RV crv;
CK_ULONG pOSLen = *pulOperationStateLen;
/* make sure we're legal */
crv = pk11_GetContext(hSession, &context, PK11_HASH, PR_TRUE, &session);
@ -5105,6 +5167,10 @@ CK_RV NSC_GetOperationState(CK_SESSION_HANDLE hSession,
if (pOperationState == NULL) {
pk11_FreeSession(session);
return CKR_OK;
} else {
if (pOSLen < *pulOperationStateLen) {
return CKR_BUFFER_TOO_SMALL;
}
}
PORT_Memcpy(pOperationState,&context->type,sizeof(PK11ContextType));
pOperationState += sizeof(PK11ContextType);