//+--------------------------------------------------------------------------- // // Microsoft Windows // Copyright (C) Microsoft Corporation, 1992 - 1995. // // File: sigsys.c // // Contents: // // Classes: // // Functions: // // History: 09-23-97 jbanes LSA integration stuff. // //---------------------------------------------------------------------------- #include #include #include #include SP_STATUS SPVerifySignature( HCRYPTPROV hProv, DWORD dwCapiFlags, PPUBLICKEY pPublic, ALG_ID aiHash, PBYTE pbData, DWORD cbData, PBYTE pbSig, DWORD cbSig, BOOL fHashData) { HCRYPTKEY hPublicKey = 0; HCRYPTHASH hHash = 0; PBYTE pbSigBuff = NULL; SP_STATUS pctRet; if(hProv == 0 || pPublic == NULL) { pctRet = SP_LOG_RESULT(PCT_INT_INTERNAL_ERROR); goto cleanup; } pbSigBuff = SPExternalAlloc(cbSig); if(pbSigBuff == NULL) { pctRet = SP_LOG_RESULT(SEC_E_INSUFFICIENT_MEMORY); goto cleanup; } // // Create public key. // if(!SchCryptImportKey(hProv, (PBYTE)pPublic->pPublic, pPublic->cbPublic, 0, 0, &hPublicKey, dwCapiFlags)) { SP_LOG_RESULT(GetLastError()); pctRet = PCT_ERR_ILLEGAL_MESSAGE; goto cleanup; } // // Hash data. // if(!SchCryptCreateHash(hProv, aiHash, 0, 0, &hHash, dwCapiFlags)) { SP_LOG_RESULT(GetLastError()); pctRet = PCT_ERR_ILLEGAL_MESSAGE; goto cleanup; } if(!fHashData) { // set hash value if(!SchCryptSetHashParam(hHash, HP_HASHVAL, pbData, 0, dwCapiFlags)) { SP_LOG_RESULT(GetLastError()); pctRet = PCT_ERR_ILLEGAL_MESSAGE; goto cleanup; } } else { if(!SchCryptHashData(hHash, pbData, cbData, 0, dwCapiFlags)) { SP_LOG_RESULT(GetLastError()); pctRet = PCT_ERR_ILLEGAL_MESSAGE; goto cleanup; } } if(pPublic->pPublic->aiKeyAlg == CALG_DSS_SIGN) { BYTE rgbTempSig[DSA_SIGNATURE_SIZE]; DWORD cbTempSig; // Remove DSS ASN1 goo around signature and convert it to // little endian. cbTempSig = sizeof(rgbTempSig); if(!CryptDecodeObject(X509_ASN_ENCODING, X509_DSS_SIGNATURE, pbSig, cbSig, 0, rgbTempSig, &cbTempSig)) { SP_LOG_RESULT(GetLastError()); pctRet = PCT_ERR_ILLEGAL_MESSAGE; goto cleanup; } memcpy(pbSigBuff, rgbTempSig, cbTempSig); cbSig = cbTempSig; } else { // Convert signature to little endian. ReverseMemCopy(pbSigBuff, pbSig, cbSig); } if(!SchCryptVerifySignature(hHash, pbSigBuff, cbSig, hPublicKey, NULL, 0, dwCapiFlags)) { DebugLog((DEB_WARN, "Signature Verify Failed: %x\n", GetLastError())); pctRet = SP_LOG_RESULT(PCT_INT_MSG_ALTERED); goto cleanup; } pctRet = PCT_ERR_OK; cleanup: if(hPublicKey) { SchCryptDestroyKey(hPublicKey, dwCapiFlags); } if(hHash) { SchCryptDestroyHash(hHash, dwCapiFlags); } if(pbSigBuff != NULL) { SPExternalFree(pbSigBuff); } return pctRet; } SP_STATUS SignHashUsingCred( PSPCredential pCred, ALG_ID aiHash, PBYTE pbHash, DWORD cbHash, PBYTE pbSignature, PDWORD pcbSignature) { HCRYPTHASH hHash; DWORD cbSignatureBuffer; SP_STATUS pctRet; if(pCred == NULL) { return SP_LOG_RESULT(PCT_INT_INTERNAL_ERROR); } cbSignatureBuffer = *pcbSignature; if(pCred->hProv) { // Sign hash using local CSP handle. if(!CryptCreateHash(pCred->hProv, aiHash, 0, 0, &hHash)) { SP_LOG_RESULT(GetLastError()); return PCT_ERR_ILLEGAL_MESSAGE; } if(!CryptSetHashParam(hHash, HP_HASHVAL, pbHash, 0)) { SP_LOG_RESULT(GetLastError()); CryptDestroyHash(hHash); return PCT_ERR_ILLEGAL_MESSAGE; } if(!CryptSignHash(hHash, pCred->dwKeySpec, NULL, 0, pbSignature, pcbSignature)) { SP_LOG_RESULT(GetLastError()); CryptDestroyHash(hHash); return PCT_ERR_ILLEGAL_MESSAGE; } CryptDestroyHash(hHash); } else if(pCred->hRemoteProv) { // Sign hash via a call to the application process. pctRet = SignHashUsingCallback(pCred->hRemoteProv, pCred->dwKeySpec, aiHash, pbHash, cbHash, pbSignature, pcbSignature, FALSE); if(pctRet != PCT_ERR_OK) { return SP_LOG_RESULT(pctRet); } } else { DebugLog((DEB_ERROR, "We have no key with which to sign!\n")); return SP_LOG_RESULT(PCT_INT_INTERNAL_ERROR); } if(pCred->dwExchSpec == SP_EXCH_DH_PKCS3) { BYTE rgbTempSig[DSA_SIGNATURE_SIZE]; // Add DSS ASN1 goo around signature. if(*pcbSignature != DSA_SIGNATURE_SIZE) { return SP_LOG_RESULT(PCT_ERR_ILLEGAL_MESSAGE); } memcpy(rgbTempSig, pbSignature, DSA_SIGNATURE_SIZE); *pcbSignature = cbSignatureBuffer; if(!CryptEncodeObject(X509_ASN_ENCODING, X509_DSS_SIGNATURE, rgbTempSig, pbSignature, pcbSignature)) { SP_LOG_RESULT(GetLastError()); return PCT_ERR_ILLEGAL_MESSAGE; } } else { // Convert signature to big endian. ReverseInPlace(pbSignature, *pcbSignature); } return PCT_ERR_OK; }