зеркало из https://github.com/mozilla/pjs.git
bug 150704, PK11_Finalize can crash because softoken does not implement C_XXXFinal correctly
This commit is contained in:
Родитель
fb0381c091
Коммит
41ebe0592b
|
@ -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 */
|
||||
pk11_SetContextByType(session, PK11_ENCRYPT, NULL);
|
||||
pk11_FreeContext(context);
|
||||
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 */
|
||||
pk11_SetContextByType(session, PK11_DECRYPT, NULL);
|
||||
pk11_FreeContext(context);
|
||||
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;
|
||||
pk11_SetContextByType(session, PK11_HASH, NULL);
|
||||
pk11_FreeContext(context);
|
||||
} else {
|
||||
*pulDigestLen = 0;
|
||||
*pulDigestLen = context->maxLen;
|
||||
}
|
||||
|
||||
pk11_SetContextByType(session, PK11_HASH, NULL);
|
||||
pk11_FreeContext(context);
|
||||
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);
|
||||
|
|
Загрузка…
Ссылка в новой задаче