Skip to content

Commit

Permalink
bug 150704, PK11_Finalize can crash because softoken does not impleme…
Browse files Browse the repository at this point in the history
…nt C_XXXFinal correctly
  • Loading branch information
ian.mcgreer%sun.com committed Jun 19, 2002
1 parent 5e203a9 commit cba66be
Show file tree
Hide file tree
Showing 2 changed files with 100 additions and 17 deletions.
27 changes: 22 additions & 5 deletions security/nss/lib/pk11wrap/pk11skey.c
Expand Up @@ -4020,41 +4020,58 @@ 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;
break;
}

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;
}

Expand Down
90 changes: 78 additions & 12 deletions security/nss/lib/softoken/pkcs11c.c
Expand Up @@ -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;
Expand Down Expand Up @@ -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) {
Expand All @@ -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;
}
Expand All @@ -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
Expand All @@ -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;
Expand Down Expand Up @@ -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) {
Expand All @@ -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;
}
Expand All @@ -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
Expand All @@ -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;
}
Expand Down Expand Up @@ -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:
Expand All @@ -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:
Expand All @@ -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;
Expand Down Expand Up @@ -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 */
Expand All @@ -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;
}
Expand Down Expand Up @@ -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;
}
Expand Down Expand Up @@ -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;
}
Expand Down Expand Up @@ -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;
}

Expand Down Expand Up @@ -1855,6 +1902,7 @@ CK_RV NSC_SignInit(CK_SESSION_HANDLE hSession,
context->cipherInfo = privKey;
context->destroy = (PK11Destroy)pk11_Null;
}
context->maxLen = nsslowkey_PrivateModulusLen(privKey);
break;

case CKM_DSA_SHA1:
Expand All @@ -1876,6 +1924,7 @@ CK_RV NSC_SignInit(CK_SESSION_HANDLE hSession,
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:
Expand Down Expand Up @@ -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);
Expand All @@ -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;
Expand All @@ -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) {
Expand All @@ -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;
Expand Down Expand Up @@ -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);
Expand All @@ -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);
Expand Down

0 comments on commit cba66be

Please sign in to comment.