/*++ Copyright (C) Microsoft Corporation, 2001 Module Name: csplib.c General Cryptographic Service Provider Library Abstract: Author: Dan Griffin Notes: --*/ #include #include #include #include #include #include #include #include #include #include "csplib.h" // // This global must be provided by the "Local" CSP using this library. // extern LOCAL_CSP_INFO LocalCspInfo; #define PROVPATH L"SOFTWARE\\Microsoft\\Cryptography\\Defaults\\Provider\\" // // DllInitialize stores the image path in here during process attach. // CHAR l_szImagePath[MAX_PATH]; // // Debug Support // // This uses the debug routines from dsysdbg.h // Debug output will only be available in chk // bits. // DEFINE_DEBUG2(Csplib) #if DBG #define DebugLog(x) CsplibDebugPrint x #else #define DebugLog(x) #endif #define DEB_ERROR 0x00000001 #define DEB_WARN 0x00000002 #define DEB_TRACE 0x00000004 #define DEB_TRACE_FUNC 0x00000080 #define DEB_TRACE_MEM 0x00000100 #define TRACE_STUFF 0x00000200 static DEBUG_KEY MyDebugKeys[] = { {DEB_ERROR, "Error"}, {DEB_WARN, "Warning"}, {DEB_TRACE, "Trace"}, {DEB_TRACE_FUNC, "TraceFuncs"}, {DEB_TRACE_MEM, "TraceMem"}, {0, NULL} }; #define LOG_BEGIN_FUNCTION(x) \ { DebugLog((DEB_TRACE_FUNC, "%s: Entering\n", #x)); } #define LOG_END_FUNCTION(x, y) \ { DebugLog((DEB_TRACE_FUNC, "%s: Leaving, status: 0x%x\n", #x, y)); } #define LOG_CHECK_ALLOC(x) \ { if (NULL == x) { \ dwSts = ERROR_NOT_ENOUGH_MEMORY; \ DebugLog((DEB_TRACE_MEM, "%s: Allocation failed\n", #x)); \ goto Ret; \ } } // // Function: ApplyPKCS1SigningFormat // // Purpose: Format a buffer with PKCS 1 for signing // // Notes: // If the padding and formatting is successful, the *ppbPKCS1Format parameter // will be allocated by this routine and must be freed by the caller. // DWORD WINAPI ApplyPKCS1SigningFormat( IN ALG_ID HashAlgid, IN BYTE *pbHash, IN DWORD cbHash, IN DWORD dwFlags, IN DWORD cbModulus, OUT PBYTE *ppbPKCS1Format) { DWORD dwSts = ERROR_SUCCESS; BYTE *pbStart = NULL; BYTE *pbEnd = NULL; BYTE bTmp = 0; DWORD i = 0; DWORD cbAvailableData = cbModulus; // pPubKey->datalen; *ppbPKCS1Format = NULL; // // We know we need at least 3 bytes of padding space. // // Note, the final (third) byte of padding is the zeroed-byte at // location pbPKCS1Format[cbModulus - 1]. // cbAvailableData -= 3; // In a few scenarios (involving small RSA keys), the new large SHA // hashes are too big to be signed by the specified key. if (cbHash > cbAvailableData) { dwSts = (DWORD) NTE_BAD_LEN; goto Ret; } *ppbPKCS1Format = (PBYTE) CspAllocH(cbModulus); LOG_CHECK_ALLOC(*ppbPKCS1Format); // insert the block type (*ppbPKCS1Format)[cbModulus - 2] = 0x01; // Padding byte #1 // insert the type I padding memset(*ppbPKCS1Format, 0xff, cbModulus - 2); // Reverse it for (i = 0; i < cbHash; i++) (*ppbPKCS1Format)[i] = pbHash[cbHash - (i + 1)]; cbAvailableData -= cbHash; if ( 0 == (CRYPT_NOHASHOID & dwFlags)) { switch (HashAlgid) { case CALG_MD2: // PKCS delimit the hash value pbEnd = (LPBYTE)md2Encodings[0]; pbStart = *ppbPKCS1Format + cbHash; bTmp = *pbEnd++; while (0 < bTmp--) *pbStart++ = *pbEnd++; *pbStart++ = 0; break; case CALG_MD4: // PKCS delimit the hash value pbEnd = (LPBYTE)md4Encodings[0]; pbStart = *ppbPKCS1Format + cbHash; bTmp = *pbEnd++; while (0 < bTmp--) *pbStart++ = *pbEnd++; *pbStart++ = 0; break; case CALG_MD5: // PKCS delimit the hash value pbEnd = (LPBYTE)md5Encodings[0]; pbStart = *ppbPKCS1Format + cbHash; bTmp = *pbEnd++; while (0 < bTmp--) *pbStart++ = *pbEnd++; *pbStart++ = 0; break; case CALG_SHA: // PKCS delimit the hash value pbEnd = (LPBYTE)shaEncodings[0]; pbStart = *ppbPKCS1Format + cbHash; bTmp = *pbEnd++; while (0 < bTmp--) *pbStart++ = *pbEnd++; *pbStart++ = 0; break; case CALG_SSL3_SHAMD5: // No PKCS padding pbStart = *ppbPKCS1Format + cbHash; *pbStart++ = 0; break; case CALG_SHA_256: pbEnd = (LPBYTE) sha256Encodings[0]; pbStart = *ppbPKCS1Format + cbHash; bTmp = *pbEnd++; if (bTmp > cbAvailableData) { dwSts = (DWORD) NTE_BAD_LEN; goto Ret; } while (0 < bTmp--) *pbStart++ = *pbEnd++; *pbStart++ = 0; // Padding byte #2 break; case CALG_SHA_384: pbEnd = (LPBYTE) sha384Encodings[0]; pbStart = *ppbPKCS1Format + cbHash; bTmp = *pbEnd++; if (bTmp > cbAvailableData) { dwSts = (DWORD) NTE_BAD_LEN; goto Ret; } while (0 < bTmp--) *pbStart++ = *pbEnd++; *pbStart++ = 0; // Padding byte #2 break; case CALG_SHA_512: pbEnd = (LPBYTE) sha512Encodings[0]; pbStart = *ppbPKCS1Format + cbHash; bTmp = *pbEnd++; if (bTmp > cbAvailableData) { dwSts = (DWORD) NTE_BAD_LEN; goto Ret; } while (0 < bTmp--) *pbStart++ = *pbEnd++; *pbStart++ = 0; // Padding byte #2 break; default: dwSts = (DWORD)NTE_BAD_ALGID; goto Ret; } } else { (*ppbPKCS1Format)[cbHash] = 0x00; } Ret: if (ERROR_SUCCESS != dwSts && NULL != *ppbPKCS1Format) { CspFreeH(*ppbPKCS1Format); *ppbPKCS1Format = NULL; } return dwSts; } // // Function: VerifyPKCS2Padding // DWORD WINAPI VerifyPKCS2Padding( IN PBYTE pbPaddedData, IN DWORD cbModulus, OUT PBYTE *ppbData, OUT PDWORD pcbData) { DWORD dwSts = ERROR_SUCCESS; PBYTE pbData = NULL; DWORD cbData = 0; DWORD z = 0; *ppbData = NULL; *pcbData = 0; if ((pbPaddedData[cbModulus - 2] != PKCS_BLOCKTYPE_2) || (pbPaddedData[cbModulus - 1] != 0)) { dwSts = NTE_BAD_DATA; goto Ret; } cbData = cbModulus - 3; while ((cbData > 0) && (pbPaddedData[cbData])) cbData--; pbData = (PBYTE) CspAllocH(cbData); LOG_CHECK_ALLOC(pbData); // Reverse the session key bytes for (z = 0; z < cbData; ++z) pbData[z] = pbPaddedData[cbData - z - 1]; *ppbData = pbData; pbData = NULL; *pcbData = cbData; Ret: if (pbData) CspFreeH(pbData); return dwSts; } // // Function: GetLocalCspInfo // PLOCAL_CSP_INFO GetLocalCspInfo(void) { return &LocalCspInfo; } // // Function: InitializeLocalCallInfo // DWORD InitializeLocalCallInfo( IN PLOCAL_CALL_INFO pLocalCallInfo) { *pLocalCallInfo = FALSE; return ERROR_SUCCESS; } // // Function: SetLocalCallInfo // // Purpose: The local CSP uses this function to indicate to functions in // this library whether execution of a given API should continue // after the local CSP has returned. // void SetLocalCallInfo( IN OUT PLOCAL_CALL_INFO pLocalCallInfo, IN BOOL fContinue) { *pLocalCallInfo = fContinue; } // // Function: CheckLocalCallInfo // BOOL CheckLocalCallInfo( IN PLOCAL_CALL_INFO pLocalCallInfo, IN DWORD dwSts, OUT BOOL *pfSuccess) { if (FALSE == *pLocalCallInfo) *pfSuccess = (ERROR_SUCCESS == dwSts); return *pLocalCallInfo; } // // Memory Management // // // Function: CspAllocH // LPVOID WINAPI CspAllocH( IN SIZE_T cBytes) { return HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, cBytes); } // // Function: CspFreeH // void WINAPI CspFreeH( IN LPVOID pMem) { HeapFree(GetProcessHeap(), 0, pMem); } // // Function: CspReAllocH // LPVOID WINAPI CspReAllocH( IN LPVOID pMem, IN SIZE_T cBytes) { return HeapReAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, pMem, cBytes); } // // Critical Section Management // // // Function: CspInitializeCriticalSection // DWORD CspInitializeCriticalSection( IN CRITICAL_SECTION *pcs) { __try { InitializeCriticalSection(pcs); } __except (EXCEPTION_EXECUTE_HANDLER) { return ERROR_NOT_ENOUGH_MEMORY; } return ERROR_SUCCESS; } // // Function: CspEnterCriticalSection // DWORD CspEnterCriticalSection( IN CRITICAL_SECTION *pcs) { __try { EnterCriticalSection(pcs); } __except (EXCEPTION_EXECUTE_HANDLER) { return ERROR_NOT_ENOUGH_MEMORY; } return ERROR_SUCCESS; } // // Function: CspLeaveCriticalSection // void CspLeaveCriticalSection( IN CRITICAL_SECTION *pcs) { LeaveCriticalSection(pcs); } // // Function: CspDeleteCriticalSection // void CspDeleteCriticalSection( IN CRITICAL_SECTION *pcs) { DeleteCriticalSection(pcs); } // // Registration Helpers // // // Function: RegOpenProviderKey // DWORD WINAPI RegOpenProviderKey( IN OUT HKEY *phProviderKey, IN REGSAM samDesired) { DWORD cbProv = 0; LPWSTR wszProv = NULL; DWORD dwSts = ERROR_SUCCESS; DWORD dwIgn = 0; PLOCAL_CSP_INFO pLocalCspInfo = GetLocalCspInfo(); *phProviderKey = 0; cbProv = (wcslen(PROVPATH) + wcslen(pLocalCspInfo->wszProviderName) + 1) * sizeof(WCHAR); wszProv = (LPWSTR) CspAllocH(cbProv); if (NULL == wszProv) { dwSts = ERROR_NOT_ENOUGH_MEMORY; goto Ret; } swprintf( wszProv, L"%s%s", PROVPATH, pLocalCspInfo->wszProviderName); // // Create or open in local machine for provider // dwSts = RegCreateKeyExW(HKEY_LOCAL_MACHINE, wszProv, 0L, L"", REG_OPTION_NON_VOLATILE, samDesired, NULL, phProviderKey, &dwIgn); if (ERROR_SUCCESS != dwSts) goto Ret; Ret: if (wszProv) CspFreeH(wszProv); if (ERROR_SUCCESS != dwSts && 0 != *phProviderKey) RegCloseKey(*phProviderKey); return dwSts; } // // Function: CreateUuidContainerName // DWORD WINAPI CreateUuidContainerName( IN PUSER_CONTEXT pUserCtx) { UUID Uuid; LPWSTR wszUuid = NULL; DWORD dwSts = ERROR_SUCCESS; dwSts = (DWORD) UuidCreate(&Uuid); if (RPC_S_OK != dwSts) goto Ret; dwSts = (DWORD) UuidToStringW(&Uuid, &wszUuid); if (RPC_S_OK != dwSts) goto Ret; pUserCtx->wszBaseContainerName = wszUuid; pUserCtx->fBaseContainerNameIsRpcUuid = TRUE; wszUuid = NULL; Ret: if (wszUuid) RpcStringFreeW(&wszUuid); return dwSts; } // // Function: DeleteUserContext // DWORD DeleteUserContext( IN PUSER_CONTEXT pUserContext) { DWORD dwSts = ERROR_SUCCESS; if (pUserContext->pVTableW) { if (pUserContext->pVTableW->pbContextInfo) { CspFreeH(pUserContext->pVTableW->pbContextInfo); pUserContext->pVTableW = NULL; } if (pUserContext->pVTableW->pszProvName) { CspFreeH(pUserContext->pVTableW->pszProvName); pUserContext->pVTableW->pszProvName = NULL; } CspFreeH(pUserContext->pVTableW); pUserContext->pVTableW = NULL; } if (pUserContext->wszBaseContainerName) { if (pUserContext->fBaseContainerNameIsRpcUuid) RpcStringFreeW(&pUserContext->wszBaseContainerName); else CspFreeH(pUserContext->wszBaseContainerName); pUserContext->wszBaseContainerName = NULL; } if (pUserContext->wszContainerNameFromCaller) { CspFreeH(pUserContext->wszContainerNameFromCaller); pUserContext->wszContainerNameFromCaller = NULL; } if (pUserContext->wszUniqueContainerName) { CspFreeH(pUserContext->wszUniqueContainerName); pUserContext->wszUniqueContainerName = NULL; } if (pUserContext->hSupportProv) { if (! CryptReleaseContext(pUserContext->hSupportProv, 0)) dwSts = GetLastError(); pUserContext->hSupportProv = 0; } return dwSts; } // // Function: DeleteKeyContext // DWORD DeleteKeyContext( IN PKEY_CONTEXT pKeyContext) { PLOCAL_CSP_INFO pLocalCspInfo = GetLocalCspInfo(); LOCAL_CALL_INFO LocalCallInfo; DWORD dwSts = ERROR_SUCCESS; InitializeLocalCallInfo(&LocalCallInfo); if (pKeyContext->hSupportKey) { if (! CryptDestroyKey(pKeyContext->hSupportKey)) dwSts = GetLastError(); pKeyContext->hSupportKey = 0; } if (pKeyContext->pvLocalKeyContext) { if (pLocalCspInfo->pfnLocalDestroyKey) { pLocalCspInfo->pfnLocalDestroyKey( pKeyContext, &LocalCallInfo); pKeyContext->pvLocalKeyContext = NULL; } } return dwSts; } // // Function: DeleteHashContext // DWORD DeleteHashContext( IN PHASH_CONTEXT pHashContext) { PLOCAL_CSP_INFO pLocalCspInfo = GetLocalCspInfo(); LOCAL_CALL_INFO LocalCallInfo; DWORD dwSts = ERROR_SUCCESS; InitializeLocalCallInfo(&LocalCallInfo); if (pHashContext->hSupportHash) { if (! CryptDestroyHash(pHashContext->hSupportHash)) dwSts = GetLastError(); pHashContext->hSupportHash = 0; } if (pHashContext->pvLocalHashContext) { if (pLocalCspInfo->pfnLocalDestroyHash) { pLocalCspInfo->pfnLocalDestroyHash( pHashContext, &LocalCallInfo); pHashContext->pvLocalHashContext = NULL; } } return dwSts; } /* - CPAcquireContext - * Purpose: * The CPAcquireContext function is used to acquire a context * handle to a cryptographic service provider (CSP). * * * Parameters: * OUT phProv - Handle to a CSP * IN szContainer - Pointer to a string which is the * identity of the logged on user * IN dwFlags - Flags values * IN pVTable - Pointer to table of function pointers * * Returns: */ BOOL WINAPI CPAcquireContext( OUT HCRYPTPROV *phProv, IN LPCSTR szContainer, IN DWORD dwFlags, IN PVTableProvStruc pVTable) { ANSI_STRING AnsiContainer; UNICODE_STRING UnicodeContainer; ANSI_STRING AnsiProvName; UNICODE_STRING UnicodeProvName; BOOL fSuccess = FALSE; DWORD dwSts; DWORD dwError = NTE_FAIL; VTableProvStrucW VTableW; memset(&AnsiContainer, 0, sizeof(AnsiContainer)); memset(&AnsiProvName, 0, sizeof(AnsiProvName)); memset(&UnicodeContainer, 0, sizeof(UnicodeContainer)); memset(&UnicodeProvName, 0, sizeof(UnicodeProvName)); memset(&VTableW, 0, sizeof(VTableW)); if (szContainer) { RtlInitAnsiString(&AnsiContainer, szContainer); dwSts = RtlAnsiStringToUnicodeString( &UnicodeContainer, &AnsiContainer, TRUE); if (STATUS_SUCCESS != dwSts) { dwError = RtlNtStatusToDosError(dwSts); goto Ret; } } VTableW.cbContextInfo = pVTable->cbContextInfo; VTableW.dwProvType = pVTable->dwProvType; VTableW.FuncReturnhWnd = pVTable->FuncReturnhWnd; VTableW.pbContextInfo = pVTable->pbContextInfo; VTableW.Version = pVTable->Version; RtlInitAnsiString(&AnsiProvName, pVTable->pszProvName); dwSts = RtlAnsiStringToUnicodeString( &UnicodeProvName, &AnsiProvName, TRUE); if (STATUS_SUCCESS != dwSts) { dwError = RtlNtStatusToDosError(dwSts); goto Ret; } VTableW.pszProvName = UnicodeProvName.Buffer; if (! CPAcquireContextW( phProv, szContainer ? UnicodeContainer.Buffer : NULL, dwFlags, &VTableW)) { dwError = GetLastError(); goto Ret; } fSuccess = TRUE; Ret: if (szContainer) RtlFreeUnicodeString(&UnicodeContainer); RtlFreeUnicodeString(&UnicodeProvName); if (! fSuccess) SetLastError(dwError); return fSuccess; } /* - CPAcquireContextW - * Purpose: * The CPAcquireContextW function is used to acquire a context * handle to a cryptographic service provider (CSP). using * UNICODE strings. This is an optional entry point for a CSP. * It is not used prior to Whistler. There it is used if * exported by the CSP image, otherwise any string conversions * are done, and CPAcquireContext is called. * * * Parameters: * OUT phProv - Handle to a CSP * IN szContainer - Pointer to a string which is the * identity of the logged on user * IN dwFlags - Flags values * IN pVTable - Pointer to table of function pointers * * Returns: */ BOOL WINAPI CPAcquireContextW( OUT HCRYPTPROV *phProv, IN LPCWSTR szContainer, IN DWORD dwFlags, IN PVTableProvStrucW pVTable) { PUSER_CONTEXT pUserContext = NULL; LOCAL_CALL_INFO LocalCallInfo; DWORD dwSts = ERROR_SUCCESS; BOOL fSuccess = FALSE; PLOCAL_CSP_INFO pLocalCspInfo = GetLocalCspInfo(); InitializeLocalCallInfo(&LocalCallInfo); // // Invalid to specify a container name with // VERIFYCONTEXT. // if ( (CRYPT_VERIFYCONTEXT & dwFlags) && NULL != szContainer) { dwSts = NTE_BAD_FLAGS; goto Ret; } pUserContext = (PUSER_CONTEXT) CspAllocH(sizeof(USER_CONTEXT)); LOG_CHECK_ALLOC(pUserContext); if (szContainer) { pUserContext->wszContainerNameFromCaller = (LPWSTR) CspAllocH((1 + wcslen(szContainer)) * sizeof(WCHAR)); LOG_CHECK_ALLOC(pUserContext->wszContainerNameFromCaller); wcscpy( pUserContext->wszContainerNameFromCaller, szContainer); } pUserContext->dwFlags = dwFlags; // // Copy the VTableProvStruc that we received from advapi, since // the info in the struct may be useful later. // pUserContext->pVTableW = (PVTableProvStrucW) CspAllocH(sizeof(VTableProvStrucW)); LOG_CHECK_ALLOC(pUserContext->pVTableW); // Copy the provider name pUserContext->pVTableW->pszProvName = (LPWSTR) CspAllocH((1 + wcslen(pVTable->pszProvName)) * sizeof(WCHAR)); LOG_CHECK_ALLOC(pUserContext->pVTableW->pszProvName); wcscpy( pUserContext->pVTableW->pszProvName, pVTable->pszProvName); // Copy the context information, if any if (pVTable->pbContextInfo) { pUserContext->pVTableW->pbContextInfo = (PBYTE) CspAllocH(pVTable->cbContextInfo); LOG_CHECK_ALLOC(pUserContext->pVTableW->pbContextInfo); memcpy( pUserContext->pVTableW->pbContextInfo, pVTable->pbContextInfo, pVTable->cbContextInfo); pUserContext->pVTableW->cbContextInfo = pVTable->cbContextInfo; } // Copy the rest of the ProvStruc pUserContext->pVTableW->dwProvType = pVTable->dwProvType; pUserContext->pVTableW->FuncReturnhWnd = pVTable->FuncReturnhWnd; pUserContext->pVTableW->FuncVerifyImage = pVTable->FuncVerifyImage; pUserContext->pVTableW->Version = pVTable->Version; if (! CryptAcquireContextW( &pUserContext->hSupportProv, NULL, pLocalCspInfo->wszSupportProviderName, pLocalCspInfo->dwSupportProviderType, CRYPT_VERIFYCONTEXT)) { dwSts = GetLastError(); goto Ret; } dwSts = pLocalCspInfo->pfnLocalAcquireContext( pUserContext, &LocalCallInfo); if (ERROR_SUCCESS != dwSts) goto Ret; if (CRYPT_DELETEKEYSET & dwFlags) { DeleteUserContext(pUserContext); CspFreeH(pUserContext); pUserContext = NULL; } else *phProv = (HCRYPTPROV) pUserContext; Ret: if (ERROR_SUCCESS != dwSts) { DeleteUserContext(pUserContext); CspFreeH(pUserContext); SetLastError(dwSts); fSuccess = FALSE; } else fSuccess = TRUE; return fSuccess; } /* - CPReleaseContext - * Purpose: * The CPReleaseContext function is used to release a * context created by CryptAcquireContext. * * Parameters: * IN phProv - Handle to a CSP * IN dwFlags - Flags values * * Returns: */ BOOL WINAPI CPReleaseContext( IN HCRYPTPROV hProv, IN DWORD dwFlags) { PUSER_CONTEXT pUserContext = (PUSER_CONTEXT) hProv; PLOCAL_CSP_INFO pLocalCspInfo = GetLocalCspInfo(); BOOL fSuccess = TRUE; DWORD dwSts = ERROR_SUCCESS; LOCAL_CALL_INFO LocalCallInfo; InitializeLocalCallInfo(&LocalCallInfo); dwSts = pLocalCspInfo->pfnLocalReleaseContext( pUserContext, dwFlags, &LocalCallInfo); if (ERROR_SUCCESS != dwSts) fSuccess = FALSE; // // Try to free the user context structure, regardless of what the // local CSP replied in the above call. // DeleteUserContext(pUserContext); if (FALSE == fSuccess) SetLastError(dwSts); return fSuccess; } /* - CPGenKey - * Purpose: * Generate cryptographic keys * * * Parameters: * IN hProv - Handle to a CSP * IN Algid - Algorithm identifier * IN dwFlags - Flags values * OUT phKey - Handle to a generated key * * Returns: */ BOOL WINAPI CPGenKey( IN HCRYPTPROV hProv, IN ALG_ID Algid, IN DWORD dwFlags, OUT HCRYPTKEY *phKey) { DWORD dwSts = ERROR_SUCCESS; PKEY_CONTEXT pKeyCtx = NULL; PUSER_CONTEXT pUserCtx = (PUSER_CONTEXT) hProv; BOOL fSuccess = FALSE; PLOCAL_CSP_INFO pLocalCspInfo = GetLocalCspInfo(); LOCAL_CALL_INFO LocalCallInfo; InitializeLocalCallInfo(&LocalCallInfo); *phKey = 0; pKeyCtx = (PKEY_CONTEXT) CspAllocH(sizeof(KEY_CONTEXT)); LOG_CHECK_ALLOC(pKeyCtx); pKeyCtx->Algid = Algid; pKeyCtx->dwFlags = 0x0000ffff & dwFlags; pKeyCtx->cKeyBits = dwFlags >> 16; pKeyCtx->pUserContext = pUserCtx; if (pLocalCspInfo->pfnLocalGenKey) { dwSts = pLocalCspInfo->pfnLocalGenKey( pKeyCtx, &LocalCallInfo); if (! CheckLocalCallInfo(&LocalCallInfo, dwSts, &fSuccess)) goto Ret; } if (! CryptGenKey( pUserCtx->hSupportProv, Algid, dwFlags, &pKeyCtx->hSupportKey)) { dwSts = GetLastError(); goto Ret; } fSuccess = TRUE; Ret: if (TRUE == fSuccess) { *phKey = (HCRYPTKEY) pKeyCtx; pKeyCtx = NULL; } if (pKeyCtx) { DeleteKeyContext(pKeyCtx); CspFreeH(pKeyCtx); } if (FALSE == fSuccess) SetLastError(dwSts); return fSuccess; } /* - CPDeriveKey - * Purpose: * Derive cryptographic keys from base data * * * Parameters: * IN hProv - Handle to a CSP * IN Algid - Algorithm identifier * IN hBaseData - Handle to base data * IN dwFlags - Flags values * OUT phKey - Handle to a generated key * * Returns: */ BOOL WINAPI CPDeriveKey( IN HCRYPTPROV hProv, IN ALG_ID Algid, IN HCRYPTHASH hHash, IN DWORD dwFlags, OUT HCRYPTKEY *phKey) { DWORD dwSts = ERROR_SUCCESS; PKEY_CONTEXT pKeyCtx = NULL; PUSER_CONTEXT pUserCtx = (PUSER_CONTEXT) hProv; PHASH_CONTEXT pHashCtx = (PHASH_CONTEXT) hHash; BOOL fSuccess = FALSE; PLOCAL_CSP_INFO pLocalCspInfo = GetLocalCspInfo(); LOCAL_CALL_INFO LocalCallInfo; *phKey = 0; InitializeLocalCallInfo(&LocalCallInfo); pKeyCtx = (PKEY_CONTEXT) CspAllocH(sizeof(KEY_CONTEXT)); LOG_CHECK_ALLOC(pKeyCtx); pKeyCtx->pUserContext = pUserCtx; pKeyCtx->Algid = Algid; pKeyCtx->cKeyBits = dwFlags >> 16; pKeyCtx->dwFlags = dwFlags & 0x0000ffff; if (pLocalCspInfo->pfnLocalDeriveKey) { dwSts = pLocalCspInfo->pfnLocalDeriveKey( pKeyCtx, pHashCtx, &LocalCallInfo); if (! CheckLocalCallInfo(&LocalCallInfo, dwSts, &fSuccess)) goto Ret; } if (! CryptDeriveKey( pUserCtx->hSupportProv, Algid, pHashCtx->hSupportHash, dwFlags, &pKeyCtx->hSupportKey)) { dwSts = GetLastError(); goto Ret; } *phKey = (HCRYPTKEY) pKeyCtx; pKeyCtx = NULL; fSuccess = TRUE; Ret: if (pKeyCtx) { DeleteKeyContext(pKeyCtx); CspFreeH(pKeyCtx); } if (FALSE == fSuccess) SetLastError(dwSts); return fSuccess; } /* - CPDestroyKey - * Purpose: * Destroys the cryptographic key that is being referenced * with the hKey parameter * * * Parameters: * IN hProv - Handle to a CSP * IN hKey - Handle to a key * * Returns: */ BOOL WINAPI CPDestroyKey( IN HCRYPTPROV hProv, IN HCRYPTKEY hKey) { DWORD dwSts = ERROR_SUCCESS; PUSER_CONTEXT pUserCtx = (PUSER_CONTEXT) hProv; PKEY_CONTEXT pKeyCtx = (PKEY_CONTEXT) hKey; dwSts = DeleteKeyContext(pKeyCtx); CspFreeH(pKeyCtx); if (ERROR_SUCCESS != dwSts) SetLastError(dwSts); return (ERROR_SUCCESS == dwSts); } /* - CPSetKeyParam - * Purpose: * Allows applications to customize various aspects of the * operations of a key * * Parameters: * IN hProv - Handle to a CSP * IN hKey - Handle to a key * IN dwParam - Parameter number * IN pbData - Pointer to data * IN dwFlags - Flags values * * Returns: */ BOOL WINAPI CPSetKeyParam( IN HCRYPTPROV hProv, IN HCRYPTKEY hKey, IN DWORD dwParam, IN CONST BYTE *pbData, IN DWORD dwFlags) { DWORD dwSts = ERROR_SUCCESS; PUSER_CONTEXT pUserCtx = (PUSER_CONTEXT) hProv; PKEY_CONTEXT pKeyCtx = (PKEY_CONTEXT) hKey; LOCAL_CALL_INFO LocalCallInfo; BOOL fSuccess = FALSE; PLOCAL_CSP_INFO pLocalCspInfo = GetLocalCspInfo(); InitializeLocalCallInfo(&LocalCallInfo); if (pLocalCspInfo->pfnLocalSetKeyParam) { dwSts = pLocalCspInfo->pfnLocalSetKeyParam( pKeyCtx, dwParam, (PBYTE) pbData, dwFlags, &LocalCallInfo); if (! CheckLocalCallInfo(&LocalCallInfo, dwSts, &fSuccess)) goto Ret; } if (! CryptSetKeyParam( pKeyCtx->hSupportKey, dwParam, pbData, dwFlags)) { dwSts = GetLastError(); goto Ret; } fSuccess = TRUE; Ret: if (FALSE == fSuccess) SetLastError(dwSts); return fSuccess; } /* - CPGetKeyParam - * Purpose: * Allows applications to get various aspects of the * operations of a key * * Parameters: * IN hProv - Handle to a CSP * IN hKey - Handle to a key * IN dwParam - Parameter number * OUT pbData - Pointer to data * IN pdwDataLen - Length of parameter data * IN dwFlags - Flags values * * Returns: */ BOOL WINAPI CPGetKeyParam( IN HCRYPTPROV hProv, IN HCRYPTKEY hKey, IN DWORD dwParam, OUT LPBYTE pbData, IN OUT LPDWORD pcbDataLen, IN DWORD dwFlags) { DWORD dwSts = ERROR_SUCCESS; PUSER_CONTEXT pUserCtx = (PUSER_CONTEXT) hProv; PKEY_CONTEXT pKeyCtx = (PKEY_CONTEXT) hKey; LOCAL_CALL_INFO LocalCallInfo; PLOCAL_CSP_INFO pLocalCspInfo = GetLocalCspInfo(); BOOL fSuccess = FALSE; InitializeLocalCallInfo(&LocalCallInfo); if (pLocalCspInfo->pfnLocalGetKeyParam) { dwSts = pLocalCspInfo->pfnLocalGetKeyParam( pKeyCtx, dwParam, pbData, pcbDataLen, dwFlags, &LocalCallInfo); if (! CheckLocalCallInfo(&LocalCallInfo, dwSts, &fSuccess)) goto Ret; } if (! CryptGetKeyParam( pKeyCtx->hSupportKey, dwParam, pbData, pcbDataLen, dwFlags)) { dwSts = GetLastError(); goto Ret; } Ret: if (FALSE == fSuccess) SetLastError(dwSts); return fSuccess; } /* - CPSetProvParam - * Purpose: * Allows applications to customize various aspects of the * operations of a provider * * Parameters: * IN hProv - Handle to a CSP * IN dwParam - Parameter number * IN pbData - Pointer to data * IN dwFlags - Flags values * * Returns: */ BOOL WINAPI CPSetProvParam( IN HCRYPTPROV hProv, IN DWORD dwParam, IN CONST BYTE *pbData, IN DWORD dwFlags) { DWORD dwSts = ERROR_SUCCESS; PUSER_CONTEXT pUserCtx = (PUSER_CONTEXT) hProv; LOCAL_CALL_INFO LocalCallInfo; PLOCAL_CSP_INFO pLocalCspInfo = GetLocalCspInfo(); BOOL fSuccess = FALSE; InitializeLocalCallInfo(&LocalCallInfo); if (pLocalCspInfo->pfnLocalSetProvParam) { dwSts = pLocalCspInfo->pfnLocalSetProvParam( pUserCtx, dwParam, (PBYTE) pbData, dwFlags, &LocalCallInfo); if (! CheckLocalCallInfo(&LocalCallInfo, dwSts, &fSuccess)) goto Ret; } if (! CryptSetProvParam( pUserCtx->hSupportProv, dwParam, pbData, dwFlags)) { dwSts = GetLastError(); goto Ret; } fSuccess = TRUE; Ret: if (FALSE == fSuccess) SetLastError(dwSts); return fSuccess; } /* - CPGetProvParam - * Purpose: * Allows applications to get various aspects of the * operations of a provider * * Parameters: * IN hProv - Handle to a CSP * IN dwParam - Parameter number * OUT pbData - Pointer to data * IN OUT pdwDataLen - Length of parameter data * IN dwFlags - Flags values * * Returns: */ BOOL WINAPI CPGetProvParam( IN HCRYPTPROV hProv, IN DWORD dwParam, OUT LPBYTE pbData, IN OUT LPDWORD pcbDataLen, IN DWORD dwFlags) { DWORD dwSts = ERROR_SUCCESS; PUSER_CONTEXT pUserCtx = (PUSER_CONTEXT) hProv; BOOL fSuccess = FALSE; DWORD cbData = 0; ANSI_STRING AnsiString; UNICODE_STRING UnicodeString; BOOL fFreeAnsiString = FALSE; LOCAL_CALL_INFO LocalCallInfo; PLOCAL_CSP_INFO pLocalCspInfo = GetLocalCspInfo(); BOOL fContinue = TRUE; memset(&AnsiString, 0, sizeof(AnsiString)); memset(&UnicodeString, 0, sizeof(UnicodeString)); InitializeLocalCallInfo(&LocalCallInfo); // // First, see if the local CSP wants to service this call // if (pLocalCspInfo->pfnLocalGetProvParam) { dwSts = pLocalCspInfo->pfnLocalGetProvParam( pUserCtx, dwParam, pbData, pcbDataLen, dwFlags, &LocalCallInfo); if (! CheckLocalCallInfo(&LocalCallInfo, dwSts, &fSuccess)) goto Ret; } // // Some prov params are general enough to be serviced "globally" // by this lib. // Try those before calling the support CSP. // switch (dwParam) { case PP_CONTAINER: fContinue = FALSE; RtlInitUnicodeString( &UnicodeString, pUserCtx->wszBaseContainerName); dwSts = RtlUnicodeStringToAnsiString( &AnsiString, &UnicodeString, TRUE); if (STATUS_SUCCESS != dwSts) { dwSts = RtlNtStatusToDosError(dwSts); goto Ret; } fFreeAnsiString = TRUE; cbData = strlen(AnsiString.Buffer) + 1; if (*pcbDataLen < cbData || NULL == pbData) { *pcbDataLen = cbData; if (NULL != pbData) dwSts = ERROR_MORE_DATA; else fSuccess = TRUE; break; } *pcbDataLen = cbData; strcpy((LPSTR) pbData, AnsiString.Buffer); fSuccess = TRUE; break; case PP_UNIQUE_CONTAINER: fContinue = FALSE; RtlInitUnicodeString( &UnicodeString, pUserCtx->wszUniqueContainerName); dwSts = RtlUnicodeStringToAnsiString( &AnsiString, &UnicodeString, TRUE); if (STATUS_SUCCESS != dwSts) { dwSts = RtlNtStatusToDosError(dwSts); goto Ret; } fFreeAnsiString = TRUE; cbData = strlen(AnsiString.Buffer) + 1; if (*pcbDataLen < cbData || NULL == pbData) { *pcbDataLen = cbData; if (NULL != pbData) dwSts = ERROR_MORE_DATA; else fSuccess = TRUE; break; } *pcbDataLen = cbData; strcpy((LPSTR) pbData, AnsiString.Buffer); fSuccess = TRUE; break; case PP_NAME: fContinue = FALSE; RtlInitUnicodeString( &UnicodeString, pLocalCspInfo->wszProviderName); dwSts = RtlUnicodeStringToAnsiString( &AnsiString, &UnicodeString, TRUE); if (STATUS_SUCCESS != dwSts) { dwSts = RtlNtStatusToDosError(dwSts); goto Ret; } fFreeAnsiString = TRUE; cbData = strlen(AnsiString.Buffer) + 1; if (*pcbDataLen < cbData || NULL == pbData) { *pcbDataLen = cbData; if (NULL != pbData) dwSts = ERROR_MORE_DATA; else fSuccess = TRUE; break; } *pcbDataLen = cbData; strcpy((LPSTR) pbData, AnsiString.Buffer); fSuccess = TRUE; break; case PP_PROVTYPE: fContinue = FALSE; if (*pcbDataLen < sizeof(DWORD) || NULL == pbData) { *pcbDataLen = sizeof(DWORD); if (NULL != pbData) dwSts = ERROR_MORE_DATA; else fSuccess = TRUE; break; } *pcbDataLen = sizeof(DWORD); memcpy( pbData, (PBYTE) &pLocalCspInfo->dwProviderType, sizeof(DWORD)); fSuccess = TRUE; break; case PP_IMPTYPE: fContinue = FALSE; if (*pcbDataLen < sizeof(DWORD) || NULL == pbData) { *pcbDataLen = sizeof(DWORD); if (NULL != pbData) dwSts = ERROR_MORE_DATA; else fSuccess = TRUE; break; } *pcbDataLen = sizeof(DWORD); memcpy( pbData, (PBYTE) &pLocalCspInfo->dwImplementationType, sizeof(DWORD)); fSuccess = TRUE; break; } if (FALSE == fContinue) goto Ret; // // Try sending any request that hasn't been filtered by the above checks // to the support CSP. // if (! CryptGetProvParam( pUserCtx->hSupportProv, dwParam, pbData, pcbDataLen, dwFlags)) { dwSts = GetLastError(); goto Ret; } fSuccess = TRUE; Ret: if (fFreeAnsiString) RtlFreeAnsiString(&AnsiString); if (FALSE == fSuccess) SetLastError(dwSts); return fSuccess; } /* - CPSetHashParam - * Purpose: * Allows applications to customize various aspects of the * operations of a hash * * Parameters: * IN hProv - Handle to a CSP * IN hHash - Handle to a hash * IN dwParam - Parameter number * IN pbData - Pointer to data * IN dwFlags - Flags values * * Returns: */ BOOL WINAPI CPSetHashParam( IN HCRYPTPROV hProv, IN HCRYPTHASH hHash, IN DWORD dwParam, IN CONST BYTE *pbData, IN DWORD dwFlags) { BOOL fSuccess = FALSE; PHASH_CONTEXT pHashCtx = (PHASH_CONTEXT) hHash; LOCAL_CALL_INFO LocalCallInfo; PLOCAL_CSP_INFO pLocalCspInfo = GetLocalCspInfo(); DWORD dwSts = ERROR_SUCCESS; InitializeLocalCallInfo(&LocalCallInfo); if (pLocalCspInfo->pfnLocalSetHashParam) { dwSts = pLocalCspInfo->pfnLocalSetHashParam( pHashCtx, dwParam, (PBYTE) pbData, dwFlags, &LocalCallInfo); if (! CheckLocalCallInfo(&LocalCallInfo, dwSts, &fSuccess)) goto Ret; } if (! CryptSetHashParam( pHashCtx->hSupportHash, dwParam, pbData, dwFlags)) { dwSts = GetLastError(); goto Ret; } fSuccess = TRUE; Ret: if (FALSE == fSuccess) SetLastError(dwSts); return fSuccess; } /* - CPGetHashParam - * Purpose: * Allows applications to get various aspects of the * operations of a hash * * Parameters: * IN hProv - Handle to a CSP * IN hHash - Handle to a hash * IN dwParam - Parameter number * OUT pbData - Pointer to data * IN pdwDataLen - Length of parameter data * IN dwFlags - Flags values * * Returns: */ BOOL WINAPI CPGetHashParam( IN HCRYPTPROV hProv, IN HCRYPTHASH hHash, IN DWORD dwParam, OUT LPBYTE pbData, IN OUT LPDWORD pcbDataLen, IN DWORD dwFlags) { BOOL fSuccess = FALSE; PHASH_CONTEXT pHashCtx = (PHASH_CONTEXT) hHash; LOCAL_CALL_INFO LocalCallInfo; PLOCAL_CSP_INFO pLocalCspInfo = GetLocalCspInfo(); DWORD dwSts = ERROR_SUCCESS; InitializeLocalCallInfo(&LocalCallInfo); if (pLocalCspInfo->pfnLocalGetHashParam) { dwSts = pLocalCspInfo->pfnLocalGetHashParam( pHashCtx, dwParam, pbData, pcbDataLen, dwFlags, &LocalCallInfo); if (! CheckLocalCallInfo(&LocalCallInfo, dwSts, &fSuccess)) goto Ret; } if (! CryptGetHashParam( pHashCtx->hSupportHash, dwParam, pbData, pcbDataLen, dwFlags)) { dwSts = GetLastError(); goto Ret; } fSuccess = TRUE; Ret: if (FALSE == fSuccess) SetLastError(dwSts); return fSuccess; } /* - CPExportKey - * Purpose: * Export cryptographic keys out of a CSP in a secure manner * * * Parameters: * IN hProv - Handle to the CSP user * IN hKey - Handle to the key to export * IN hPubKey - Handle to exchange public key value of * the destination user * IN dwBlobType - Type of key blob to be exported * IN dwFlags - Flags values * OUT pbData - Key blob data * IN OUT pdwDataLen - Length of key blob in bytes * * Returns: */ BOOL WINAPI CPExportKey( IN HCRYPTPROV hProv, IN HCRYPTKEY hKey, IN HCRYPTKEY hPubKey, IN DWORD dwBlobType, IN DWORD dwFlags, OUT LPBYTE pbData, IN OUT LPDWORD pcbDataLen) { BOOL fSuccess = FALSE; DWORD dwSts = ERROR_SUCCESS; PUSER_CONTEXT pUserCtx = (PUSER_CONTEXT) hProv; PKEY_CONTEXT pKeyCtx = (PKEY_CONTEXT) hKey; PKEY_CONTEXT pPubKeyCtx = (PKEY_CONTEXT) hPubKey; LOCAL_CALL_INFO LocalCallInfo; PLOCAL_CSP_INFO pLocalCspInfo = GetLocalCspInfo(); InitializeLocalCallInfo(&LocalCallInfo); if (pLocalCspInfo->pfnLocalExportKey) { dwSts = pLocalCspInfo->pfnLocalExportKey( pKeyCtx, pPubKeyCtx, dwBlobType, dwFlags, pbData, pcbDataLen, &LocalCallInfo); if (! CheckLocalCallInfo(&LocalCallInfo, dwSts, &fSuccess)) goto Ret; } if (! CryptExportKey( pKeyCtx->hSupportKey, pPubKeyCtx ? pPubKeyCtx->hSupportKey : 0, dwBlobType, dwFlags, pbData, pcbDataLen)) { dwSts = GetLastError(); goto Ret; } fSuccess = TRUE; Ret: if (FALSE == fSuccess) SetLastError(dwSts); return fSuccess; } /* - CPImportKey - * Purpose: * Import cryptographic keys * * * Parameters: * IN hProv - Handle to the CSP user * IN pbData - Key blob data * IN dwDataLen - Length of the key blob data * IN hPubKey - Handle to the exchange public key value of * the destination user * IN dwFlags - Flags values * OUT phKey - Pointer to the handle to the key which was * Imported * * Returns: */ BOOL WINAPI CPImportKey( IN HCRYPTPROV hProv, IN CONST BYTE *pbData, IN DWORD cbDataLen, IN HCRYPTKEY hPubKey, IN DWORD dwFlags, OUT HCRYPTKEY *phKey) { BOOL fSuccess = FALSE; DWORD dwSts = ERROR_SUCCESS; PUSER_CONTEXT pUserCtx = (PUSER_CONTEXT) hProv; PKEY_CONTEXT pKeyCtx = NULL; PKEY_CONTEXT pPubKeyCtx = (PKEY_CONTEXT) hPubKey; LOCAL_CALL_INFO LocalCallInfo; PLOCAL_CSP_INFO pLocalCspInfo = GetLocalCspInfo(); *phKey = 0; InitializeLocalCallInfo(&LocalCallInfo); pKeyCtx = (PKEY_CONTEXT) CspAllocH(sizeof(KEY_CONTEXT)); LOG_CHECK_ALLOC(pKeyCtx); pKeyCtx->dwFlags = dwFlags & 0x0000ffff; pKeyCtx->pUserContext = pUserCtx; if (pLocalCspInfo->pfnLocalImportKey) { dwSts = pLocalCspInfo->pfnLocalImportKey( pKeyCtx, (PBYTE) pbData, cbDataLen, pPubKeyCtx, &LocalCallInfo); if (! CheckLocalCallInfo(&LocalCallInfo, dwSts, &fSuccess)) goto Ret; } if (! CryptImportKey( pUserCtx->hSupportProv, pbData, cbDataLen, pPubKeyCtx ? pPubKeyCtx->hSupportKey : 0, dwFlags, &pKeyCtx->hSupportKey)) { dwSts = GetLastError(); goto Ret; } fSuccess = TRUE; Ret: if (TRUE == fSuccess) { *phKey = (HCRYPTKEY) pKeyCtx; pKeyCtx = NULL; } if (pKeyCtx) { DeleteKeyContext(pKeyCtx); CspFreeH(pKeyCtx); } if (FALSE == fSuccess) SetLastError(dwSts); return fSuccess; } /* - CPEncrypt - * Purpose: * Encrypt data * * * Parameters: * IN hProv - Handle to the CSP user * IN hKey - Handle to the key * IN hHash - Optional handle to a hash * IN Final - Boolean indicating if this is the final * block of plaintext * IN dwFlags - Flags values * IN OUT pbData - Data to be encrypted * IN OUT pdwDataLen - Pointer to the length of the data to be * encrypted * IN dwBufLen - Size of Data buffer * * Returns: */ BOOL WINAPI CPEncrypt( IN HCRYPTPROV hProv, IN HCRYPTKEY hKey, IN HCRYPTHASH hHash, IN BOOL fFinal, IN DWORD dwFlags, IN OUT LPBYTE pbData, IN OUT LPDWORD pcbDataLen, IN DWORD cbBufLen) { BOOL fSuccess = FALSE; DWORD dwSts = ERROR_SUCCESS; PUSER_CONTEXT pUserCtx = (PUSER_CONTEXT) hProv; PKEY_CONTEXT pKeyCtx = (PKEY_CONTEXT) hKey; PHASH_CONTEXT pHashCtx = (PHASH_CONTEXT) hHash; LOCAL_CALL_INFO LocalCallInfo; PLOCAL_CSP_INFO pLocalCspInfo = GetLocalCspInfo(); *pcbDataLen = 0; InitializeLocalCallInfo(&LocalCallInfo); if (pLocalCspInfo->pfnLocalEncrypt) { dwSts = pLocalCspInfo->pfnLocalEncrypt( pKeyCtx, pHashCtx, fFinal, dwFlags, pbData, pcbDataLen, cbBufLen, &LocalCallInfo); if (! CheckLocalCallInfo(&LocalCallInfo, dwSts, &fSuccess)) goto Ret; } if (! CryptEncrypt( pKeyCtx->hSupportKey, pHashCtx ? pHashCtx->hSupportHash : 0, fFinal, dwFlags, pbData, pcbDataLen, cbBufLen)) { dwSts = GetLastError(); goto Ret; } fSuccess = TRUE; Ret: if (FALSE == fSuccess) SetLastError(dwSts); return fSuccess; } /* - CPDecrypt - * Purpose: * Decrypt data * * * Parameters: * IN hProv - Handle to the CSP user * IN hKey - Handle to the key * IN hHash - Optional handle to a hash * IN Final - Boolean indicating if this is the final * block of ciphertext * IN dwFlags - Flags values * IN OUT pbData - Data to be decrypted * IN OUT pdwDataLen - Pointer to the length of the data to be * decrypted * * Returns: */ BOOL WINAPI CPDecrypt( IN HCRYPTPROV hProv, IN HCRYPTKEY hKey, IN HCRYPTHASH hHash, IN BOOL fFinal, IN DWORD dwFlags, IN OUT LPBYTE pbData, IN OUT LPDWORD pcbDataLen) { BOOL fSuccess = FALSE; DWORD dwSts = ERROR_SUCCESS; PUSER_CONTEXT pUserCtx = (PUSER_CONTEXT) hProv; PKEY_CONTEXT pKeyCtx = (PKEY_CONTEXT) hKey; PHASH_CONTEXT pHashCtx = (PHASH_CONTEXT) hHash; LOCAL_CALL_INFO LocalCallInfo; PLOCAL_CSP_INFO pLocalCspInfo = GetLocalCspInfo(); InitializeLocalCallInfo(&LocalCallInfo); if (pLocalCspInfo->pfnLocalDecrypt) { dwSts = pLocalCspInfo->pfnLocalDecrypt( pKeyCtx, pHashCtx, fFinal, dwFlags, pbData, pcbDataLen, &LocalCallInfo); if (! CheckLocalCallInfo(&LocalCallInfo, dwSts, &fSuccess)) goto Ret; } if (! CryptDecrypt( pKeyCtx->hSupportKey, pHashCtx ? pHashCtx->hSupportHash : 0, fFinal, dwFlags, pbData, pcbDataLen)) { dwSts = GetLastError(); goto Ret; } fSuccess = TRUE; Ret: if (FALSE == fSuccess) SetLastError(dwSts); return fSuccess; } /* - CPCreateHash - * Purpose: * initate the hashing of a stream of data * * * Parameters: * IN hUID - Handle to the user identifcation * IN Algid - Algorithm identifier of the hash algorithm * to be used * IN hKey - Optional handle to a key * IN dwFlags - Flags values * OUT pHash - Handle to hash object * * Returns: */ BOOL WINAPI CPCreateHash( IN HCRYPTPROV hProv, IN ALG_ID Algid, IN HCRYPTKEY hKey, IN DWORD dwFlags, OUT HCRYPTHASH *phHash) { BOOL fSuccess = FALSE; PHASH_CONTEXT pHashCtx = NULL; PUSER_CONTEXT pUserCtx = (PUSER_CONTEXT) hProv; PKEY_CONTEXT pKeyCtx = (PKEY_CONTEXT) hKey; DWORD dwSts = ERROR_SUCCESS; LOCAL_CALL_INFO LocalCallInfo; PLOCAL_CSP_INFO pLocalCspInfo = GetLocalCspInfo(); *phHash = 0; InitializeLocalCallInfo(&LocalCallInfo); pHashCtx = (PHASH_CONTEXT) CspAllocH(sizeof(HASH_CONTEXT)); LOG_CHECK_ALLOC(pHashCtx); pHashCtx->Algid = Algid; pHashCtx->dwFlags = dwFlags; pHashCtx->pUserContext = pUserCtx; if (pLocalCspInfo->pfnLocalCreateHash) { dwSts = pLocalCspInfo->pfnLocalCreateHash( pHashCtx, pKeyCtx, &LocalCallInfo); if (! CheckLocalCallInfo(&LocalCallInfo, dwSts, &fSuccess)) goto Ret; } if (! CryptCreateHash( pUserCtx->hSupportProv, Algid, pKeyCtx ? pKeyCtx->hSupportKey : 0, dwFlags, &pHashCtx->hSupportHash)) { dwSts = GetLastError(); goto Ret; } *phHash = (HCRYPTHASH) pHashCtx; pHashCtx = NULL; fSuccess = TRUE; Ret: if (pHashCtx) { DeleteHashContext(pHashCtx); CspFreeH(pHashCtx); } if (FALSE == fSuccess) SetLastError(dwSts); return fSuccess; } /* - CPHashData - * Purpose: * Compute the cryptograghic hash on a stream of data * * * Parameters: * IN hProv - Handle to the user identifcation * IN hHash - Handle to hash object * IN pbData - Pointer to data to be hashed * IN dwDataLen - Length of the data to be hashed * IN dwFlags - Flags values * * Returns: */ BOOL WINAPI CPHashData( IN HCRYPTPROV hProv, IN HCRYPTHASH hHash, IN CONST BYTE *pbData, IN DWORD cbDataLen, IN DWORD dwFlags) { BOOL fSuccess = FALSE; PHASH_CONTEXT pHashCtx = (PHASH_CONTEXT) hHash; PUSER_CONTEXT pUserCtx = (PUSER_CONTEXT) hProv; DWORD dwSts = ERROR_SUCCESS; LOCAL_CALL_INFO LocalCallInfo; PLOCAL_CSP_INFO pLocalCspInfo = GetLocalCspInfo(); InitializeLocalCallInfo(&LocalCallInfo); if (pLocalCspInfo->pfnLocalHashData) { dwSts = pLocalCspInfo->pfnLocalHashData( pHashCtx, pbData, cbDataLen, dwFlags, &LocalCallInfo); if (! CheckLocalCallInfo(&LocalCallInfo, dwSts, &fSuccess)) goto Ret; } if (! CryptHashData( pHashCtx->hSupportHash, pbData, cbDataLen, dwFlags)) { dwSts = GetLastError(); goto Ret; } fSuccess = TRUE; Ret: if (FALSE == fSuccess) SetLastError(dwSts); return fSuccess; } /* - CPHashSessionKey - * Purpose: * Compute the cryptograghic hash on a key object. * * * Parameters: * IN hProv - Handle to the user identifcation * IN hHash - Handle to hash object * IN hKey - Handle to a key object * IN dwFlags - Flags values * * Returns: * CRYPT_FAILED * CRYPT_SUCCEED */ BOOL WINAPI CPHashSessionKey( IN HCRYPTPROV hProv, IN HCRYPTHASH hHash, IN HCRYPTKEY hKey, IN DWORD dwFlags) { BOOL fSuccess = FALSE; PHASH_CONTEXT pHashCtx = (PHASH_CONTEXT) hHash; PUSER_CONTEXT pUserCtx = (PUSER_CONTEXT) hProv; PKEY_CONTEXT pKeyCtx = (PKEY_CONTEXT) hKey; DWORD dwSts = ERROR_SUCCESS; LOCAL_CALL_INFO LocalCallInfo; PLOCAL_CSP_INFO pLocalCspInfo = GetLocalCspInfo(); InitializeLocalCallInfo(&LocalCallInfo); if (pLocalCspInfo->pfnLocalHashSessionKey) { dwSts = pLocalCspInfo->pfnLocalHashSessionKey( pHashCtx, pKeyCtx, dwFlags, &LocalCallInfo); if (! CheckLocalCallInfo(&LocalCallInfo, dwSts, &fSuccess)) goto Ret; } if (! CryptHashSessionKey( pHashCtx->hSupportHash, pKeyCtx ? pKeyCtx->hSupportKey : 0, dwFlags)) { dwSts = GetLastError(); goto Ret; } fSuccess = TRUE; Ret: if (FALSE == fSuccess) SetLastError(dwSts); return fSuccess; } /* - CPSignHash - * Purpose: * Create a digital signature from a hash * * * Parameters: * IN hProv - Handle to the user identifcation * IN hHash - Handle to hash object * IN dwKeySpec - Key pair to that is used to sign with * IN sDescription - Description of data to be signed * IN dwFlags - Flags values * OUT pbSignature - Pointer to signature data * IN OUT dwHashLen - Pointer to the len of the signature data * * Returns: */ BOOL WINAPI CPSignHash( IN HCRYPTPROV hProv, IN HCRYPTHASH hHash, IN DWORD dwKeySpec, IN LPCWSTR szDescription, IN DWORD dwFlags, OUT LPBYTE pbSignature, IN OUT LPDWORD pcbSigLen) { BOOL fSuccess = FALSE; PHASH_CONTEXT pHashCtx = (PHASH_CONTEXT) hHash; PUSER_CONTEXT pUserCtx = (PUSER_CONTEXT) hProv; DWORD dwSts = ERROR_SUCCESS; LOCAL_CALL_INFO LocalCallInfo; PLOCAL_CSP_INFO pLocalCspInfo = GetLocalCspInfo(); InitializeLocalCallInfo(&LocalCallInfo); if (pLocalCspInfo->pfnLocalSignHash) { dwSts = pLocalCspInfo->pfnLocalSignHash( pHashCtx, dwKeySpec, dwFlags, pbSignature, pcbSigLen, &LocalCallInfo); if (! CheckLocalCallInfo(&LocalCallInfo, dwSts, &fSuccess)) goto Ret; } if (! CryptSignHash( pHashCtx->hSupportHash, dwKeySpec, NULL, dwFlags, pbSignature, pcbSigLen)) { dwSts = GetLastError(); goto Ret; } fSuccess = TRUE; Ret: if (FALSE == fSuccess) SetLastError(dwSts); return fSuccess; } /* - CPDestroyHash - * Purpose: * Destroy the hash object * * * Parameters: * IN hProv - Handle to the user identifcation * IN hHash - Handle to hash object * * Returns: */ BOOL WINAPI CPDestroyHash( IN HCRYPTPROV hProv, IN HCRYPTHASH hHash) { PHASH_CONTEXT pHashCtx = (PHASH_CONTEXT) hHash; DWORD dwSts = ERROR_SUCCESS; dwSts = DeleteHashContext(pHashCtx); CspFreeH(pHashCtx); if (ERROR_SUCCESS != dwSts) SetLastError(dwSts); return (ERROR_SUCCESS == dwSts); } /* - CPVerifySignature - * Purpose: * Used to verify a signature against a hash object * * * Parameters: * IN hProv - Handle to the user identifcation * IN hHash - Handle to hash object * IN pbSignture - Pointer to signature data * IN dwSigLen - Length of the signature data * IN hPubKey - Handle to the public key for verifying * the signature * IN sDescription - String describing the signed data * IN dwFlags - Flags values * * Returns: */ BOOL WINAPI CPVerifySignature( IN HCRYPTPROV hProv, IN HCRYPTHASH hHash, IN CONST BYTE *pbSignature, IN DWORD cbSigLen, IN HCRYPTKEY hPubKey, IN LPCWSTR szDescription, IN DWORD dwFlags) { BOOL fSuccess = FALSE; PHASH_CONTEXT pHashCtx = (PHASH_CONTEXT) hHash; PUSER_CONTEXT pUserCtx = (PUSER_CONTEXT) hProv; PKEY_CONTEXT pPubKeyCtx = (PKEY_CONTEXT) hPubKey; DWORD dwSts = ERROR_SUCCESS; LOCAL_CALL_INFO LocalCallInfo; PLOCAL_CSP_INFO pLocalCspInfo = GetLocalCspInfo(); InitializeLocalCallInfo(&LocalCallInfo); if (pLocalCspInfo->pfnLocalVerifySignature) { dwSts = pLocalCspInfo->pfnLocalVerifySignature( pHashCtx, pbSignature, cbSigLen, pPubKeyCtx, dwFlags, &LocalCallInfo); if (! CheckLocalCallInfo(&LocalCallInfo, dwSts, &fSuccess)) goto Ret; } if (! CryptVerifySignature( pHashCtx->hSupportHash, pbSignature, cbSigLen, pPubKeyCtx->hSupportKey, NULL, dwFlags)) { dwSts = GetLastError(); goto Ret; } fSuccess = TRUE; Ret: if (FALSE == fSuccess) SetLastError(dwSts); return fSuccess; } /* - CPGenRandom - * Purpose: * Used to fill a buffer with random bytes * * * Parameters: * IN hProv - Handle to the user identifcation * IN dwLen - Number of bytes of random data requested * IN OUT pbBuffer - Pointer to the buffer where the random * bytes are to be placed * * Returns: */ BOOL WINAPI CPGenRandom( IN HCRYPTPROV hProv, IN DWORD cbLen, OUT LPBYTE pbBuffer) { BOOL fSuccess = FALSE; PUSER_CONTEXT pUserCtx = (PUSER_CONTEXT) hProv; DWORD dwSts = ERROR_SUCCESS; LOCAL_CALL_INFO LocalCallInfo; PLOCAL_CSP_INFO pLocalCspInfo = GetLocalCspInfo(); InitializeLocalCallInfo(&LocalCallInfo); if (pLocalCspInfo->pfnLocalGenRandom) { dwSts = pLocalCspInfo->pfnLocalGenRandom( pUserCtx, cbLen, pbBuffer, &LocalCallInfo); if (! CheckLocalCallInfo(&LocalCallInfo, dwSts, &fSuccess)) goto Ret; } if (! CryptGenRandom( pUserCtx->hSupportProv, cbLen, pbBuffer)) { dwSts = GetLastError(); goto Ret; } fSuccess = TRUE; Ret: if (FALSE == fSuccess) SetLastError(dwSts); return fSuccess; } /* - CPGetUserKey - * Purpose: * Gets a handle to a permanent user key * * * Parameters: * IN hProv - Handle to the user identifcation * IN dwKeySpec - Specification of the key to retrieve * OUT phUserKey - Pointer to key handle of retrieved key * * Returns: */ BOOL WINAPI CPGetUserKey( IN HCRYPTPROV hProv, IN DWORD dwKeySpec, OUT HCRYPTKEY *phUserKey) { BOOL fSuccess = FALSE; PUSER_CONTEXT pUserCtx = (PUSER_CONTEXT) hProv; PKEY_CONTEXT pKeyCtx = NULL; DWORD dwSts = ERROR_SUCCESS; LOCAL_CALL_INFO LocalCallInfo; PLOCAL_CSP_INFO pLocalCspInfo = GetLocalCspInfo(); *phUserKey = 0; InitializeLocalCallInfo(&LocalCallInfo); pKeyCtx = (PKEY_CONTEXT) CspAllocH(sizeof(KEY_CONTEXT)); LOG_CHECK_ALLOC(pKeyCtx); pKeyCtx->Algid = dwKeySpec; pKeyCtx->pUserContext = pUserCtx; if (pLocalCspInfo->pfnLocalGetUserKey) { dwSts = pLocalCspInfo->pfnLocalGetUserKey( pKeyCtx, &LocalCallInfo); if (! CheckLocalCallInfo(&LocalCallInfo, dwSts, &fSuccess)) goto Ret; } if (! CryptGetUserKey( pUserCtx->hSupportProv, dwKeySpec, &pKeyCtx->hSupportKey)) { dwSts = GetLastError(); goto Ret; } fSuccess = TRUE; Ret: if (fSuccess) { *phUserKey = (HCRYPTKEY) pKeyCtx; pKeyCtx = NULL; } if (pKeyCtx) { DeleteKeyContext(pKeyCtx); CspFreeH(pKeyCtx); } if (FALSE == fSuccess) SetLastError(dwSts); return fSuccess; } /* - CPDuplicateHash - * Purpose: * Duplicates the state of a hash and returns a handle to it. * This is an optional entry. Typically it only occurs in * SChannel related CSPs. * * Parameters: * IN hUID - Handle to a CSP * IN hHash - Handle to a hash * IN pdwReserved - Reserved * IN dwFlags - Flags * IN phHash - Handle to the new hash * * Returns: */ BOOL WINAPI CPDuplicateHash( IN HCRYPTPROV hProv, IN HCRYPTHASH hHash, IN LPDWORD pdwReserved, IN DWORD dwFlags, OUT HCRYPTHASH *phHash) { PUSER_CONTEXT pUserCtx = (PUSER_CONTEXT) hProv; PHASH_CONTEXT pHashCtx = (PHASH_CONTEXT) hHash; PHASH_CONTEXT pNewHashCtx = NULL; DWORD dwSts = ERROR_SUCCESS; BOOL fSuccess = FALSE; PLOCAL_CSP_INFO pLocalCspInfo = GetLocalCspInfo(); LOCAL_CALL_INFO LocalCallInfo; *phHash = 0; InitializeLocalCallInfo(&LocalCallInfo); pNewHashCtx = (PHASH_CONTEXT) CspAllocH(sizeof(HASH_CONTEXT)); LOG_CHECK_ALLOC(pNewHashCtx); pNewHashCtx->pUserContext = pUserCtx; pNewHashCtx->dwFlags = dwFlags; if (pLocalCspInfo->pfnLocalDuplicateHash) { dwSts = pLocalCspInfo->pfnLocalDuplicateHash( pHashCtx, pdwReserved, pNewHashCtx, &LocalCallInfo); if (! CheckLocalCallInfo(&LocalCallInfo, dwSts, &fSuccess)) goto Ret; } if (! CryptDuplicateHash( pHashCtx->hSupportHash, pdwReserved, dwFlags, &pNewHashCtx->hSupportHash)) { dwSts = GetLastError(); goto Ret; } *phHash = (HCRYPTHASH) pNewHashCtx; pNewHashCtx = NULL; fSuccess = TRUE; Ret: if (pNewHashCtx) { DeleteHashContext(pNewHashCtx); CspFreeH(pNewHashCtx); } if (FALSE == fSuccess) SetLastError(dwSts); return fSuccess; } /* - CPDuplicateKey - * Purpose: * Duplicates the state of a key and returns a handle to it. * This is an optional entry. Typically it only occurs in * SChannel related CSPs. * * Parameters: * IN hUID - Handle to a CSP * IN hKey - Handle to a key * IN pdwReserved - Reserved * IN dwFlags - Flags * IN phKey - Handle to the new key * * Returns: */ BOOL WINAPI CPDuplicateKey( IN HCRYPTPROV hProv, IN HCRYPTKEY hKey, IN LPDWORD pdwReserved, IN DWORD dwFlags, OUT HCRYPTKEY *phKey) { PUSER_CONTEXT pUserCtx = (PUSER_CONTEXT) hProv; PKEY_CONTEXT pKeyCtx = (PKEY_CONTEXT) hKey; PKEY_CONTEXT pNewKeyCtx = NULL; BOOL fSuccess = FALSE; DWORD dwSts = ERROR_SUCCESS; LOCAL_CALL_INFO LocalCallInfo; PLOCAL_CSP_INFO pLocalCspInfo = GetLocalCspInfo(); *phKey = 0; InitializeLocalCallInfo(&LocalCallInfo); pNewKeyCtx = (PKEY_CONTEXT) CspAllocH(sizeof(KEY_CONTEXT)); LOG_CHECK_ALLOC(pNewKeyCtx); pNewKeyCtx->pUserContext = pUserCtx; pNewKeyCtx->dwFlags = dwFlags; if (pLocalCspInfo->pfnLocalDuplicateKey) { dwSts = pLocalCspInfo->pfnLocalDuplicateKey( pKeyCtx, pdwReserved, pNewKeyCtx, &LocalCallInfo); if (! CheckLocalCallInfo(&LocalCallInfo, dwSts, &fSuccess)) goto Ret; } if (! CryptDuplicateKey( pKeyCtx->hSupportKey, pdwReserved, dwFlags, &pNewKeyCtx->hSupportKey)) { dwSts = GetLastError(); goto Ret; } *phKey = (HCRYPTKEY) pNewKeyCtx; pNewKeyCtx = NULL; fSuccess = TRUE; Ret: if (pNewKeyCtx) { DeleteKeyContext(pNewKeyCtx); CspFreeH(pNewKeyCtx); } if (FALSE == fSuccess) SetLastError(dwSts); return fSuccess; } // // Function: DllInitialize // BOOL WINAPI DllInitialize( IN PVOID hmod, IN ULONG Reason, IN PCONTEXT Context) // Unused parameter { DWORD dwLen = 0; static BOOL fLoadedStrings = FALSE; static BOOL fInitializedCspState = FALSE; BOOL fSuccess = FALSE; PLOCAL_CSP_INFO pLocalCspInfo = GetLocalCspInfo(); switch (Reason) { case DLL_PROCESS_ATTACH: // Get our image name. dwLen = GetModuleBaseName( GetCurrentProcess(), hmod, l_szImagePath, sizeof(l_szImagePath) / sizeof(l_szImagePath[0])); if (0 == dwLen) return FALSE; DisableThreadLibraryCalls(hmod); fSuccess = TRUE; break; case DLL_PROCESS_DETACH: fSuccess = TRUE; break; } if (pLocalCspInfo->pfnLocalDllInitialize) { fSuccess = pLocalCspInfo->pfnLocalDllInitialize( hmod, Reason, Context); } return fSuccess; } // // Function: DllRegisterServer // STDAPI DllRegisterServer( void) { HKEY hKey = 0; DWORD dwVal = 0; DWORD dwProvType = PROV_RSA_FULL; DWORD dwSts = ERROR_SUCCESS; PLOCAL_CSP_INFO pLocalCspInfo = GetLocalCspInfo(); dwSts = RegOpenProviderKey(&hKey, KEY_ALL_ACCESS); if (ERROR_SUCCESS != dwSts) goto Ret; // // Set Image path // dwSts = RegSetValueExA(hKey, "Image Path", 0L, REG_SZ, (LPBYTE) l_szImagePath, strlen(l_szImagePath) + 1); if (ERROR_SUCCESS != dwSts) goto Ret; // // Set Type // dwSts = RegSetValueExA(hKey, "Type", 0L, REG_DWORD, (LPBYTE) &pLocalCspInfo->dwProviderType, sizeof(DWORD)); if (ERROR_SUCCESS != dwSts) goto Ret; // // Place signature in file value // dwSts = RegSetValueExA(hKey, "SigInFile", 0L, REG_DWORD, (LPBYTE)&dwVal, sizeof(DWORD)); if (ERROR_SUCCESS != dwSts) goto Ret; // // Add CSP default configuration // if (pLocalCspInfo->pfnLocalDllRegisterServer) dwSts = pLocalCspInfo->pfnLocalDllRegisterServer(); Ret: if (hKey) RegCloseKey(hKey); return dwSts; } // // Function: DllUnregisterServer // STDAPI DllUnregisterServer( void) { PLOCAL_CSP_INFO pLocalCspInfo = GetLocalCspInfo(); if (pLocalCspInfo->pfnLocalDllUnregisterServer) return pLocalCspInfo->pfnLocalDllUnregisterServer(); else return ERROR_SUCCESS; }