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_ULONG count = 0;
CK_RV crv; CK_RV crv;
unsigned char stackBuf[256];
unsigned char *buffer = NULL;
if (!context->ownSession) { if (!context->ownSession) {
return SECSuccess; return SECSuccess;
} }
finalize:
switch (context->operation) { switch (context->operation) {
case CKA_ENCRYPT: case CKA_ENCRYPT:
crv=PK11_GETTAB(context->slot)->C_EncryptFinal(context->session, crv=PK11_GETTAB(context->slot)->C_EncryptFinal(context->session,
NULL,&count); buffer, &count);
break; break;
case CKA_DECRYPT: case CKA_DECRYPT:
crv = PK11_GETTAB(context->slot)->C_DecryptFinal(context->session, crv = PK11_GETTAB(context->slot)->C_DecryptFinal(context->session,
NULL,&count); buffer, &count);
break; break;
case CKA_SIGN: case CKA_SIGN:
crv=PK11_GETTAB(context->slot)->C_SignFinal(context->session, crv=PK11_GETTAB(context->slot)->C_SignFinal(context->session,
NULL,&count); buffer, &count);
break; break;
case CKA_VERIFY: case CKA_VERIFY:
crv=PK11_GETTAB(context->slot)->C_VerifyFinal(context->session, crv=PK11_GETTAB(context->slot)->C_VerifyFinal(context->session,
NULL,count); buffer, count);
break; break;
case CKA_DIGEST: case CKA_DIGEST:
crv=PK11_GETTAB(context->slot)->C_DigestFinal(context->session, crv=PK11_GETTAB(context->slot)->C_DigestFinal(context->session,
NULL,&count); buffer, &count);
break; break;
default: default:
crv = CKR_OPERATION_NOT_INITIALIZED; crv = CKR_OPERATION_NOT_INITIALIZED;
@ -4052,9 +4055,23 @@ pk11_Finalize(PK11Context *context)
} }
if (crv != CKR_OK) { 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) ); PORT_SetError( PK11_MapError(crv) );
return SECFailure; 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; return SECSuccess;
} }

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

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