Example #1
0
QCSP::PinStatus QCSP::login( const TokenData &t )
{
	if( !d->h )
		return PinUnknown;

	PinDialog dialog( PinDialog::Pin2Type, t, qApp->activeWindow() );
	if( !dialog.exec() )
		return PinCanceled;
	return CryptSetProvParam( d->h, PP_SIGNATURE_PIN, LPBYTE(dialog.text().utf16()), 0 ) ? PinOK : PinUnknown;
}
bool TarjetaCAPI::establecerPIN(const ArsCadena &pin, ArsCadena &msg)
{
	bool ok;

	ok = isConectado();
	if (ok)
	{
		// por defecto, la mayoría los los CSP hacen la comprobación del PIN en la
		// llamada al CryptSetProvParam (al menos el CSP de Siemens y el de Starcos)
		// Sin embargo, hay otros CSP (como el de Ceres) que utilizan otro sistema
		// para comprobar el PIN.
		// En la especialización de "TarjetaCAPI" correspondiente, se debe codificar
		// la comprobación con el método necesario
		ok = CryptSetProvParam(getHandle(), TIPO_PIN, pin.cadena(), 0);
		if (ok)
			msg = "El PIN es correcto.";
		else
			msg = GetMensajeErrorEstablecerPIN(GetLastError());
	}
	else
		msg = "No se puede establecer el PIN si la tarjeta está cerrada.";

	return (ok);
}
Example #3
0
int  main (int argc, char *argv[])
{


    DWORD dwProvType = 75;   
    DWORD data_len = 0;			    
    BYTE *oid = NULL;			    
    DWORD dwBlobLen = 0;		    
    DWORD cAlg = (ALG_CLASS_DATA_ENCRYPT | ALG_TYPE_BLOCK | 31);

	LPCSTR SourceName = NULL;
	LPCSTR Psdw = NULL;

	HANDLE hCurrProc = GetCurrentProcess();
	char patch[] = {0x80,0xbd,0x1c,0x00,0x00,0x00,0x98,0x75,0x07,0xc6,0x85,0x1c,0x00,0x00,0x00,0x9c,0x90,0x90,0x90,0x90,0x90,0x90}; ///!!!
	int patchLen = sizeof(patch);
	DWORD previous = 0;

	DWORD writeAddr = 0x11BC2;// INITIALIZED with offset!!!  //0x611E1BC2;


	/// PARSE COMMAND PARAMETERS HERE
	for (int n = 1;n < argc;n++) {
		if (n+1 >= argc)
			break;
		if (strcmp(argv[n],"-p") == 0) {
			Psdw = argv[++n];
		}
		if (strcmp(argv[n],"-s") == 0) {
			SourceName = argv[++n];
		}
	}
	if (!Psdw || !SourceName) {
		printf("[!] Dude, u specified incorrect parameters :/\n\tUsage: %s -s <source container name> -p <container password>",argv[0]);
		exit(1);
	}


    if(!CryptAcquireContextA(
	&hProvResponder, 
	"\\\\.\\Registry\\DestCopy", //Hardcoded name for container we create!!!
	NULL,
	dwProvType,
	CRYPT_NEWKEYSET | CRYPT_SILENT))
    {
		HandleError("Error during CryptAcquireContext");
    }


    if(!CryptAcquireContextA(
	&hProvSender, 
	SourceName, 
	NULL, 
	dwProvType, 
	0)) 
    {
		HandleError("Error during CryptAcquireContext");
    }

	/// FIND ADDRESS TO PATCH
	HMODULE hModules[1024];
	DWORD needed;
	if (EnumProcessModules(hCurrProc,hModules,1024,&needed)) {
		for (int i = 0; i < (needed / sizeof(HMODULE)); i++ )
        {
            char szModName[1024];

            if ( GetModuleFileNameA( hModules[i], szModName, sizeof(szModName)))
            {
				if (StrStrA(szModName, "cpcspi.dll")) {
					writeAddr += (DWORD)hModules[i];
					printf("[+] Address in memory for patching is '%08X'.\n",writeAddr);
					break;
				}
            }
        }
	}

	
	/// !!!
	printf("[+] Now we patch process memory, patch size is '%i' bytes...",patchLen);
	VirtualProtectEx(hCurrProc, (void*)writeAddr, 2, PAGE_EXECUTE_READWRITE, &previous);
	WriteProcessMemory(hCurrProc, (void*)writeAddr, &patch, patchLen, NULL);
	printf("Ok\n");

	printf("[+] Now we export container '%s'...\n",SourceName);

	if(!CryptGetProvParam( 
	hProvSender, 
	92, 
	NULL, 
	&data_len, 
	0))
    {
		HandleError("Error computing buffer length");
    }

    oid = (BYTE *)malloc( data_len );
    if( !oid )
		HandleError("Out of memory.");


    if(!CryptGetProvParam( 
	hProvSender, 
	92, 
	oid, 
	&data_len, 
	0))
    {
		HandleError("Error during CryptGetProvParam");
    }


    if(!CryptSetProvParam(
	hProvResponder, 
	92, 
	oid, 
	0 ))
    {
		free( oid );
		HandleError("Error during CryptSetProvParam");
    }

    free( oid );

    data_len = 0;


    if(!CryptGetProvParam( 
	hProvSender, 
	93, 
	NULL, 
	&data_len, 
	0))
    {
		HandleError("Error computing buffer length");
    }

	/// SPECIFY PASSWORD FOR CONTAINER HERE
	if(!CryptSetProvParam( hProvSender,PP_SIGNATURE_PIN,(LPBYTE)Psdw,0))
	{
	    HandleError("Error during CryptSetProvParam");
	}

    oid = (BYTE *)malloc( data_len );
    if( !oid )
		HandleError("Out of memory");

    if(!CryptGetProvParam( 
	hProvSender, 
	93, 
	oid, 
	&data_len, 
	0))
    {
		free( oid );
		HandleError("Error during CryptGetProvParam");
    }

    if(!CryptSetProvParam(
	hProvResponder, 
	93, 
	oid, 
	0 ))
    {
		free( oid );
		HandleError("Error during CryptSetProvParam");
    }
    free( oid );


    if(!CryptGetUserKey( 
	hProvSender, 
	AT_KEYEXCHANGE, 
	&hSenderKey )) 
    {
		HandleError("Error during CryptGetUserKey private key");
    }		

	
    if(!CryptGenKey(
	hProvSender, 
	(ALG_CLASS_KEY_EXCHANGE | ALG_TYPE_DH | 37), 
	CRYPT_EXPORTABLE, 
	&hSenderEphemKey)) 
    {
		HandleError("ERROR -- CryptGenKey");
    }
	
	
    if(!CryptGenKey(
	hProvResponder, 
	(ALG_CLASS_KEY_EXCHANGE | ALG_TYPE_DH | 37), 
	CRYPT_EXPORTABLE | CRYPT_PREGEN,
	&hResponderEphemKey))
    {
		HandleError("ERROR -- CryptGenKey");
    }
	
	
    if(!CryptGetKeyParam( 
	hSenderEphemKey, 
	106, 
	NULL, 
	&dwBlobLen, 
	0))
    {
		HandleError("Error computing BLOB length");
    }

    pbKeyBlob = (BYTE*)malloc(dwBlobLen);
    if(!pbKeyBlob)
		HandleError("Out of memory");


    if(!CryptGetKeyParam( 
	hSenderEphemKey, 
	106, 
	pbKeyBlob, 
	&dwBlobLen, 
	0))
    {
		HandleError("Error during CryptGetProvParam");
    }

    if(!CryptSetKeyParam(
	hResponderEphemKey, 
	106, 
	pbKeyBlob, 
	0))
    {
		HandleError("Error during CryptSetProvParam");
    }

    free(pbKeyBlob);
    pbKeyBlob = NULL; 
    dwBlobLen = 0;


    if(!CryptSetKeyParam(
	hResponderEphemKey, 
	KP_X, 
	NULL, 
	0))
    {
		HandleError("Error during CryptSetKeyParam");
    }

    if(!CryptExportKey(
	hSenderEphemKey,
	0, 
	PUBLICKEYBLOB,
	0, 
	NULL,
	&dwBlobLen ))
    {
		HandleError("Error computing BLOB length");
    }

    pbKeyBlob = (BYTE*)malloc(dwBlobLen);
    if(!pbKeyBlob) 
		HandleError("Out of memory");

    if(!CryptExportKey(
	hSenderEphemKey,
	0, 
	PUBLICKEYBLOB,
	0, 
	pbKeyBlob,
	&dwBlobLen ))
    {
		HandleError("Error during CryptExportKey");
    }


    if(!CryptImportKey(
	hProvResponder, 
	pbKeyBlob, 
	dwBlobLen, 
	hResponderEphemKey, 
	0, 
	&hResponderAgreeKey))
    {
		HandleError("Error during CryptImportKey ephemeral key");
    }


    free(pbKeyBlob);
    pbKeyBlob = NULL; 
    dwBlobLen = 0;


    if(!CryptExportKey(
	hResponderEphemKey,
	0, 
	PUBLICKEYBLOB,
	0, 
	NULL,
	&dwBlobLen ))
    {
		HandleError("Error computing BLOB length");
    }

    pbKeyBlob = (BYTE*)malloc(dwBlobLen);
    if(!pbKeyBlob) 
		HandleError("Out of memory");

    if(!CryptExportKey(
	hResponderEphemKey,
	0, 
	PUBLICKEYBLOB,
	0, 
	pbKeyBlob,
	&dwBlobLen ))
    {
		HandleError("Error during CryptExportKey");
    }

 

    if(!CryptImportKey(
	hProvSender, 
	pbKeyBlob, 
	dwBlobLen, 
	hSenderEphemKey, 
	0, 
	&hSenderAgreeKey))
    {
		HandleError("Error during CryptImportKey ephemeral key");
    }


    free(pbKeyBlob);
    pbKeyBlob = NULL; 
    dwBlobLen = 0;


    if(!CryptSetKeyParam(
	hSenderAgreeKey,
	KP_ALGID, 
	(BYTE*)&cAlg,
	0 ))
    {
		HandleError("Error during CryptSetKeyParam agree key");
    }


    if(!CryptSetKeyParam(
	hResponderAgreeKey,
	KP_ALGID, 
	(BYTE*)&cAlg,
	0 ))
    {
		HandleError("Error during CryptSetKeyParam agree key");
    }
	

    if(!CryptExportKey(
	hSenderKey,
	hSenderAgreeKey, 
	PRIVATEKEYBLOB,
	0, 
	NULL,
	&dwBlobLen ))
    {
		HandleError("Error computing BLOB length");
    }

    pbKeyBlob = (BYTE*)malloc(dwBlobLen);
    if(!pbKeyBlob) 
		HandleError("Out of memory");

    if(!CryptExportKey(
	hSenderKey,
	hSenderAgreeKey, 
	PRIVATEKEYBLOB,
	0, 
	pbKeyBlob,
	&dwBlobLen ))
    {
		HandleError("Error during CryptExportKey");
    }



    if(!CryptImportKey(
	hProvResponder, 
	pbKeyBlob, 
	dwBlobLen, 
	hResponderAgreeKey, 
	0,
	&hResponderKey))
    {
		HandleError("Error during CryptImportKey private key");
    }


    free(pbKeyBlob);
    pbKeyBlob = NULL; 
    dwBlobLen = 0;



    if(!CryptGetKeyParam( 
	hSenderKey, 
	KP_CERTIFICATE, 
	NULL, 
	&dwBlobLen, 
	0))
    {
		HandleError("Error computing BLOB length");
    }

    pbKeyBlob = (BYTE*)malloc(dwBlobLen);

    if(!pbKeyBlob)
    {
		HandleError("Out of memory");
    }


    if(!CryptGetKeyParam( 
	hSenderKey, 
	KP_CERTIFICATE, 
	pbKeyBlob, 
	&dwBlobLen, 
	0))
    {
		HandleError("Error during CryptGetProvParam");
    }

    if(!CryptSetKeyParam(
	hResponderKey, 
	KP_CERTIFICATE, 
	pbKeyBlob, 
	0))
    {
		HandleError("Error during CryptSetProvParam");
    }

	printf("[+] D0n3!!!\n");

    CleanUp();
    return 0;
}
Example #4
0
/*-
 * _gnutls_privkey_import_system:
 * @pkey: The private key
 * @url: The URL of the key
 *
 * This function will import the given private key to the abstract
 * #gnutls_privkey_t type. 
 *
 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
 *   negative error value.
 *
 * Since: 3.4.0
 *
 -*/
int _gnutls_privkey_import_system_url(gnutls_privkey_t pkey, const char *url)
{
#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP)
    return gnutls_assert_val(GNUTLS_E_UNIMPLEMENTED_FEATURE);
#else
	uint8_t id[MAX_WID_SIZE];
	HCERTSTORE store = NULL;
	size_t id_size;
	const CERT_CONTEXT *cert = NULL;
	CRYPT_HASH_BLOB blob;
	CRYPT_KEY_PROV_INFO *kpi = NULL;
	NCRYPT_KEY_HANDLE nc = NULL;
	HCRYPTPROV hCryptProv = NULL;
	NCRYPT_PROV_HANDLE sctx = NULL;
	DWORD kpi_size;
	SECURITY_STATUS r;
	int ret, enc_too = 0;
	WCHAR algo_str[64];
	DWORD algo_str_size = 0;
	priv_st *priv;
	DWORD i, dwErrCode = 0;

	if (ncrypt_init == 0)
		return gnutls_assert_val(GNUTLS_E_UNIMPLEMENTED_FEATURE);

	if (url == NULL)
		return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);

	priv = gnutls_calloc(1, sizeof(*priv));
	if (priv == NULL)
		return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);

	id_size = sizeof(id);
	ret = get_id(url, id, &id_size, 0);
	if (ret < 0)
		return gnutls_assert_val(ret);

	blob.cbData = id_size;
	blob.pbData = id;

	store = CertOpenStore(CERT_STORE_PROV_SYSTEM, 0, 0, CERT_SYSTEM_STORE_CURRENT_USER, L"MY");
	if (store == NULL) {
		gnutls_assert();
		ret = GNUTLS_E_FILE_ERROR;
		goto cleanup;
	}

	cert = CertFindCertificateInStore(store,
					  X509_ASN_ENCODING,
					  0,
					  CERT_FIND_KEY_IDENTIFIER,
					  &blob, NULL);

	if (cert == NULL) {
		char buf[64];
		_gnutls_debug_log("cannot find ID: %s from %s\n",
				  _gnutls_bin2hex(id, id_size,
						  buf, sizeof(buf), NULL), url);
		ret = gnutls_assert_val(GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE);
		goto cleanup;
	}

	kpi_size = 0;
	r = CertGetCertificateContextProperty(cert, CERT_KEY_PROV_INFO_PROP_ID,
					      NULL, &kpi_size);
	if (r == 0) {
		_gnutls_debug_log("error in getting context: %d from %s\n",
				  (int)GetLastError(), url);
		ret = gnutls_assert_val(GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE);
		goto cleanup;
	}

	kpi = gnutls_malloc(kpi_size);
	if (kpi == NULL) {
		gnutls_assert();
		ret = GNUTLS_E_MEMORY_ERROR;
		goto cleanup;
	}

	r = CertGetCertificateContextProperty(cert, CERT_KEY_PROV_INFO_PROP_ID,
					      kpi, &kpi_size);
	if (r == 0) {
		_gnutls_debug_log("error in getting context: %d from %s\n",
				  (int)GetLastError(), url);
		ret = gnutls_assert_val(GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE);
		goto cleanup;
	}

	r = pNCryptOpenStorageProvider(&sctx, kpi->pwszProvName, 0);
	if (!FAILED(r)) {	/* if this works carry on with CNG */

		r = pNCryptOpenKey(sctx, &nc, kpi->pwszContainerName, 0, 0);
		if (FAILED(r)) {
			ret =
			    gnutls_assert_val
			    (GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE);
			goto cleanup;
		}

		r = pNCryptGetProperty(nc, NCRYPT_ALGORITHM_PROPERTY,
				       (BYTE *) algo_str, sizeof(algo_str),
				       &algo_str_size, 0);
		if (FAILED(r)) {
			ret =
			    gnutls_assert_val
			    (GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE);
			goto cleanup;
		}

		if (StrCmpW(algo_str, BCRYPT_RSA_ALGORITHM) == 0) {
			priv->pk = GNUTLS_PK_RSA;
			priv->sign_algo = GNUTLS_SIGN_RSA_SHA256;
			enc_too = 1;
		} else if (StrCmpW(algo_str, BCRYPT_DSA_ALGORITHM) == 0) {
			priv->pk = GNUTLS_PK_DSA;
			priv->sign_algo = GNUTLS_SIGN_DSA_SHA1;
		} else if (StrCmpW(algo_str, BCRYPT_ECDSA_P256_ALGORITHM) == 0) {
			priv->pk = GNUTLS_PK_EC;
			priv->sign_algo = GNUTLS_SIGN_ECDSA_SHA256;
		} else if (StrCmpW(algo_str, BCRYPT_ECDSA_P384_ALGORITHM) == 0) {
			priv->pk = GNUTLS_PK_EC;
			priv->sign_algo = GNUTLS_SIGN_ECDSA_SHA384;
		} else if (StrCmpW(algo_str, BCRYPT_ECDSA_P521_ALGORITHM) == 0) {
			priv->pk = GNUTLS_PK_EC;
			priv->sign_algo = GNUTLS_SIGN_ECDSA_SHA512;
		} else {
			_gnutls_debug_log("unknown key algorithm: %ls\n",
					  algo_str);
			ret = gnutls_assert_val(GNUTLS_E_UNKNOWN_PK_ALGORITHM);
			goto cleanup;
		}
		priv->nc = nc;

		ret = gnutls_privkey_import_ext3(pkey, priv, cng_sign,
						 (enc_too !=
						  0) ? cng_decrypt : NULL,
						 cng_deinit, cng_info, 0);
		if (ret < 0) {
			gnutls_assert();
			goto cleanup;
		}
	} else {
		/* this should be CAPI */
		_gnutls_debug_log
		    ("error in opening CNG keystore: %x from %ls\n", (int)r,
		     kpi->pwszProvName);

		if (CryptAcquireContextW(&hCryptProv,
					 kpi->pwszContainerName,
					 kpi->pwszProvName,
					 kpi->dwProvType, kpi->dwFlags)) {
			for (i = 0; i < kpi->cProvParam; i++)
				if (!CryptSetProvParam(hCryptProv,
						       kpi->rgProvParam[i].
						       dwParam,
						       kpi->rgProvParam[i].
						       pbData,
						       kpi->rgProvParam[i].
						       dwFlags)) {
					dwErrCode = GetLastError();
					break;
				};
		} else {
			dwErrCode = GetLastError();
		}

		if (ERROR_SUCCESS != dwErrCode) {
			_gnutls_debug_log
			    ("error in getting cryptprov: %d from %s\n",
			     (int)GetLastError(), url);
			ret =
			    gnutls_assert_val
			    (GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE);
			goto cleanup;
		}

		{
			BYTE buf[100 + sizeof(PROV_ENUMALGS_EX) * 2];
			PROV_ENUMALGS_EX *pAlgo = (PROV_ENUMALGS_EX *) buf;
			DWORD len = sizeof(buf);

			if (CryptGetProvParam
			    (hCryptProv, PP_ENUMALGS_EX, buf, &len,
			     CRYPT_FIRST)) {
				DWORD hash = 0;
				do {
					switch (pAlgo->aiAlgid) {
					case CALG_RSA_SIGN:
						priv->pk = GNUTLS_PK_RSA;
						enc_too = 1;
						break;
					case CALG_DSS_SIGN:
						priv->pk =
						    priv->pk ==
						    GNUTLS_PK_RSA ?
						    GNUTLS_PK_RSA :
						    GNUTLS_PK_DSA;
						break;
					case CALG_SHA1:
						hash = 1;
						break;
					case CALG_SHA_256:
						hash = 256;
						break;
					default:
						break;
					}

					len = sizeof(buf);	// reset the buffer size
				} while (CryptGetProvParam
					 (hCryptProv, PP_ENUMALGS_EX, buf, &len,
					  CRYPT_NEXT));

				if (priv->pk == GNUTLS_PK_DSA)
					priv->sign_algo = GNUTLS_SIGN_DSA_SHA1;
				else
					priv->sign_algo =
					    (hash >
					     1) ? GNUTLS_SIGN_RSA_SHA256 :
					    GNUTLS_SIGN_RSA_SHA1;
			}
		}

		priv->hCryptProv = hCryptProv;
		priv->dwKeySpec = kpi->dwKeySpec;

		ret = gnutls_privkey_import_ext3(pkey, priv, capi_sign,
						 (enc_too !=
						  0) ? capi_decrypt : NULL,
						 capi_deinit, capi_info, 0);
		if (ret < 0) {
			gnutls_assert();
			goto cleanup;
		}
	}
	ret = 0;
 cleanup:
	if (ret < 0) {
		if (nc != 0)
			pNCryptFreeObject(nc);
		if (hCryptProv != 0)
			CryptReleaseContext(hCryptProv, 0);
		gnutls_free(priv);
	}
	if (sctx != 0)
		pNCryptFreeObject(sctx);

	gnutls_free(kpi);

	if (cert != 0)
		CertFreeCertificateContext(cert);

	CertCloseStore(store, 0);
	return ret;
#endif
}
Example #5
0
HRESULT PasswordUtil_Check(LPCWSTR password, LPCWSTR salt, LPCWSTR passwordHash, BOOL* pResult)
{
	if(IsBadStringPtrW(password,512))
		return E_INVALIDARG;
	if(IsBadStringPtrW(salt,512))
		return E_INVALIDARG;
	if(IsBadStringPtrW(passwordHash,512))
		return E_INVALIDARG;

	if(IsBadWritePtr(pResult,sizeof(BOOL*)))
		return E_INVALIDARG;

	*pResult = FALSE;

	HRESULT hr = S_OK;

	HCRYPTPROV hProv = NULL;
	HCRYPTHASH hHash = NULL;

	WCHAR saltAndPwd[1024] = L"";

	wcsncat_s(saltAndPwd, 1024, password, 512);
	wcsncat_s(saltAndPwd, 1024, L"$",1);
	wcsncat_s(saltAndPwd, 1024, salt, 511);

	DWORD dwFlags = CRYPT_SILENT|CRYPT_MACHINE_KEYSET;
	TCHAR szContainer[50] = _T("{BDECD56B-6D48-4add-9AEE-265D537408DF}");

	CString auditMessage;

	BOOL bCreated = FALSE;

	if(!CryptAcquireContext(&hProv, szContainer, MS_ENHANCED_PROV, PROV_RSA_FULL, dwFlags))
	{
		hr = HRESULT_FROM_WIN32(GetLastError());

		if(hr==0x80090016L) // Key Not Found
		{
			bCreated = TRUE;

			if(!CryptAcquireContext(&hProv, szContainer, MS_ENHANCED_PROV, PROV_RSA_FULL, CRYPT_NEWKEYSET|dwFlags))
			{
				hr = HRESULT_FROM_WIN32(GetLastError());

				if(hr == 0x8009000FL) // Key Exists
				{
					if(CryptAcquireContext(&hProv, szContainer, MS_ENHANCED_PROV, PROV_RSA_FULL, CRYPT_DELETEKEYSET|dwFlags))
					{
						hr = S_OK;

						if(!CryptAcquireContext(&hProv, szContainer, MS_ENHANCED_PROV, PROV_RSA_FULL, CRYPT_NEWKEYSET|dwFlags))
						{
							hr = HRESULT_FROM_WIN32(GetLastError());
						}
						else
						{
							hr = S_OK;
						}
					}
					else
					{
						hr = HRESULT_FROM_WIN32(GetLastError());
					}
				}
				else
				{
					hr = S_OK;
				}
			}
			else
			{
				hr = S_OK;
			}
		}
	}

	if(SUCCEEDED(hr))
	{
		if(bCreated)
		{
			// Set DACL for this container to allow full control for everyone and for local system.
			PSECURITY_DESCRIPTOR pSd = NULL;
			LPBYTE pbDacl = NULL;

			HRESULT hr2 = CreateSecurityDescriptor(&pSd, &pbDacl);
			if(SUCCEEDED(hr2))
			{
				CryptSetProvParam(hProv, PP_KEYSET_SEC_DESCR, reinterpret_cast<LPBYTE>(pSd), DACL_SECURITY_INFORMATION);
				delete pSd;
				delete[] pbDacl;
			}
		}

		if(CryptCreateHash(hProv, CALG_MD5, 0, 0, &hHash))
		{
			//auditMessage.Format(_T("Step 2-2. Error Code: 0x%X."), hr);
			//CEventLog::AddAppLog(auditMessage, FAILED_LOGIN, EVENTLOG_WARNING_TYPE);

			if(CryptHashData(hHash, (BYTE*)saltAndPwd, (DWORD)(wcslen(saltAndPwd))*2, 0))
			{
				//auditMessage.Format(_T("Step 2-3. Error Code: 0x%X."), hr);
				//CEventLog::AddAppLog(auditMessage, FAILED_LOGIN, EVENTLOG_WARNING_TYPE);

				BYTE szData[50] = {0};
				DWORD dwDataLen = 50;

				if(CryptGetHashParam(hHash, HP_HASHVAL, szData, &dwDataLen, 0))
				{
					/*auditMessage.Format(_T("Step 2-4. Error Code: 0x%X."), hr);
					CEventLog::AddAppLog(auditMessage, FAILED_LOGIN, EVENTLOG_WARNING_TYPE);*/

					CW2A ansiPasswordHash(passwordHash);

					int passwordHashLen = static_cast<int>(strlen(ansiPasswordHash));
					int nDestLen = Base64DecodeGetRequiredLength(passwordHashLen);

					CHeapPtr<BYTE> dataBuffer;
					if(dataBuffer.AllocateBytes(nDestLen))
					{
						//auditMessage.Format(_T("Step 2-5. Error Code: 0x%X."), hr);
						//CEventLog::AddAppLog(auditMessage, FAILED_LOGIN, EVENTLOG_WARNING_TYPE);

						if(Base64Decode(ansiPasswordHash, passwordHashLen, dataBuffer, &nDestLen))
						{
							size_t testHashLength = static_cast<size_t>(dwDataLen);
							size_t validHashLength = static_cast<size_t>(nDestLen);

							*pResult = (testHashLength == validHashLength && (memcmp(szData, dataBuffer, testHashLength) == 0));
						}
					}
					else
						hr = E_OUTOFMEMORY;
				}
				else
					hr = HRESULT_FROM_WIN32(GetLastError());
			}
			else
				hr = HRESULT_FROM_WIN32(GetLastError());

			CryptDestroyHash(hHash);
		}
		else
			hr = HRESULT_FROM_WIN32(GetLastError());

		CryptReleaseContext(hProv, 0);
	}
	//else
	//	hr = HRESULT_FROM_WIN32(GetLastError());

	//auditMessage.Format(_T("Step Final. Error Code: 0x%X."), hr);
	//CEventLog::AddAppLog(auditMessage, FAILED_LOGIN, EVENTLOG_WARNING_TYPE);

	return hr;
}