// convert signature to binary // ensure to free pbSignature after use void sig2bin(void) { DWORD slen = lstrlen(signature); // determine how much space we need CryptStringToBinary(signature, slen, CRYPT_STRING_HEX_ANY, NULL, &dwSigLen, NULL, NULL); // allocate memory pbSignature = xmalloc(dwSigLen); // get the binary CryptStringToBinary(signature, slen, CRYPT_STRING_HEX_ANY, pbSignature, &dwSigLen, NULL, NULL); }
HRESULT FromBase64(LPCSTR pszString, BYTE **ppbBinary) { HRESULT hRes=S_OK; DWORD cbBinary; hRes = CryptStringToBinary(pszString, 0, CRYPT_STRING_BASE64, NULL, &cbBinary, NULL, NULL); if(FAILED(hRes)){ dprintf("[sync] failed at CryptStringToBinaryA: %d\n", GetLastError()); return E_FAIL; } *ppbBinary = (BYTE *) malloc(cbBinary+1); if (ppbBinary==NULL){ dprintf("[sync] failed at allocate buffer: %d\n", GetLastError()); return E_FAIL; } hRes = CryptStringToBinaryA(pszString, 0, CRYPT_STRING_BASE64, *ppbBinary, &cbBinary, NULL, NULL); if(FAILED(hRes)){ dprintf("[sync] failed at CryptStringToBinaryA: %d\n", GetLastError()); return E_FAIL; } *((char *)((*ppbBinary)+cbBinary)) = 0; return hRes; }
bool CCommonUtils::VerifyFile(LPCTSTR lpFileName, LPVOID lpKeyData, DWORD dwKeySize, LPCTSTR lpBase64) { LPVOID lpFileData = NULL; DWORD dwFileSize = 0; bool bRet = false; HCRYPTPROV hProv = NULL; HCRYPTKEY hKey = NULL; HCRYPTHASH hHash = NULL; LPVOID lpSignature = NULL; DWORD dwSigSize = 0; try { lpFileData = ReadFileData(lpFileName, dwFileSize); if(!lpFileData) { throw _com_error(E_FAIL); } if(!CryptAcquireContext(&hProv, NULL, NULL, PROV_RSA_FULL, 0)) { throw _com_error(HRESULT_FROM_WIN32(GetLastError())); } if(!CryptImportKey(hProv, (LPBYTE)lpKeyData, dwKeySize, NULL, 0, &hKey)) { throw _com_error(HRESULT_FROM_WIN32(GetLastError())); } if(!CryptCreateHash(hProv, CALG_SHA1, 0, 0, &hHash)) { throw _com_error(HRESULT_FROM_WIN32(GetLastError())); } if(!CryptHashData(hHash, (LPBYTE)lpFileData, dwFileSize, 0)) { throw _com_error(HRESULT_FROM_WIN32(GetLastError())); } if(!CryptStringToBinary(lpBase64, 0, CRYPT_STRING_BASE64, NULL, &dwSigSize, NULL, NULL)) { throw _com_error(HRESULT_FROM_WIN32(GetLastError())); } lpSignature = malloc(dwSigSize); if(!CryptStringToBinary(lpBase64, 0, CRYPT_STRING_BASE64, (LPBYTE)lpSignature, &dwSigSize, NULL, NULL)) { throw _com_error(HRESULT_FROM_WIN32(GetLastError())); } if(!CryptVerifySignature(hHash, (LPBYTE)lpSignature, dwSigSize, hKey, NULL, 0)) { throw _com_error(HRESULT_FROM_WIN32(GetLastError())); } bRet = true; } catch(_com_error& err) { DEBUG_PRINTF(L"Error in verifying file 0x%08X\n", err.Error()); } if(hHash) { CryptDestroyHash(hHash); } if(hProv) { CryptReleaseContext(hProv, 0); } if(lpSignature) { free(lpSignature); } if(lpFileData) { free(lpFileData); } if(lpKeyData) { free(lpKeyData); } return bRet; }
void CEstEIDIEPluginBHO::signWithCNG(BSTR id, BSTR hash, BSTR *signature) { LOG_LOCATION; #ifdef WIN_XP EstEID_log("WARNING: CNG is not supported for windows XP"); #else int methodResult = true; #define NT_SUCCESS(Status) (((NTSTATUS)(Status)) >= 0) SECURITY_STATUS secStatus = ERROR_SUCCESS; NCRYPT_KEY_HANDLE hKey = NULL; DWORD cbSignature = 0; NTSTATUS status = ((NTSTATUS)0xC0000001L); PBYTE pbSignature = NULL; PCCERT_CONTEXT certContext = NULL; HCERTSTORE cert_store; BOOL must_release_provider; int hashHexLength = _bstr_t(hash).length()/2; BCRYPT_PKCS1_PADDING_INFO padInfo; padInfo.pszAlgId = 0; switch(hashHexLength) { case BINARY_SHA1_LENGTH: padInfo.pszAlgId = NCRYPT_SHA1_ALGORITHM;break; case BINARY_SHA224_LENGTH: padInfo.pszAlgId = L"SHA224"; break; case BINARY_SHA256_LENGTH : padInfo.pszAlgId = NCRYPT_SHA256_ALGORITHM; break; case BINARY_SHA512_LENGTH: padInfo.pszAlgId = NCRYPT_SHA512_ALGORITHM; break; default: break; } try { if(!id || !strlen(CW2A(id))) { throw CryptoException(ESTEID_CERT_NOT_FOUND_ERROR); } EstEID_log("signing started, selected certificate id = %s", CW2A(id)); if(padInfo.pszAlgId == 0) { throw CryptoException(ESTEID_INVALID_HASH_ERROR); } cert_store = CertOpenStore(CERT_STORE_PROV_SYSTEM, 0, NULL, CERT_SYSTEM_STORE_CURRENT_USER | CERT_STORE_READONLY_FLAG, L"MY"); if(!cert_store) throw CryptoException(); while(certContext = CertFindCertificateInStore(cert_store, X509_ASN_ENCODING, 0, CERT_FIND_ANY, NULL, certContext)) { if(certificateMatchesId(certContext, id)) { if (!CryptAcquireCertificatePrivateKey(certContext, CRYPT_ACQUIRE_ONLY_NCRYPT_KEY_FLAG|CRYPT_ACQUIRE_COMPARE_KEY_FLAG, NULL, &hKey, NULL, &must_release_provider)) { throw CryptoException(ESTEID_CRYPTO_API_ERROR); } BYTE hashBytes[65]; CryptStringToBinary(hash, hashHexLength*2, CRYPT_STRING_HEX, hashBytes, (DWORD*)&hashHexLength, 0, 0); EstEID_log("Number of bytes stored in hashBytes buffer = %u", hashHexLength); EstEID_log("signing with %s", CW2A(padInfo.pszAlgId)); if(FAILED(secStatus = NCryptSignHash(hKey, &padInfo, (PBYTE)hashBytes, hashHexLength, NULL, 0, &cbSignature, 0))) { throw CryptoException(secStatus); } pbSignature = (PBYTE)HeapAlloc (GetProcessHeap (), 0, cbSignature); if(NULL == pbSignature){ throw CryptoException(ESTEID_CRYPTO_API_ERROR); } if(FAILED(secStatus = NCryptSignHash(hKey, &padInfo, (PBYTE)hashBytes, hashHexLength, pbSignature, cbSignature, &cbSignature, BCRYPT_PAD_PKCS1))) { throw CryptoException(secStatus); } std::stringstream ss; for (DWORD i = 0; i < cbSignature; i++) { ss << std::hex << std::setfill('0') << std::setw(2) << (short)pbSignature[i]; } *signature = _bstr_t(ss.str().c_str()).Detach(); } } } catch(CryptoException e) { *signature = _bstr_t("").Detach(); if(pbSignature) HeapFree(GetProcessHeap(), 0, pbSignature); if(hKey) NCryptFreeObject(hKey); if(certContext) CertFreeCertificateContext(certContext); if(must_release_provider && cert_store) CertCloseStore(cert_store, 0); throw CryptoException(e.windowsErrorCode); } CertFreeCertificateContext(certContext); if(must_release_provider) CertCloseStore(cert_store, 0); #endif }
void CEstEIDIEPluginBHO::signWithCSP(BSTR id, BSTR hash, BSTR *signature) { LOG_LOCATION; HCRYPTPROV cryptoProvider = NULL; HCRYPTHASH _hash = NULL ; PCCERT_CONTEXT certContext = NULL; HCERTSTORE cert_store; BOOL must_release_provider; try{ if(!id || !strlen(CW2A(id))) { throw CryptoException(ESTEID_CERT_NOT_FOUND_ERROR); } EstEID_log("signing started, selected certificate id = %s", CW2A(id)); #define VALID_HASH_LENGTH 40 if (_bstr_t(hash).length() != VALID_HASH_LENGTH) { throw CryptoException("invalid hash"); } cert_store = CertOpenStore(CERT_STORE_PROV_SYSTEM, 0, NULL, CERT_SYSTEM_STORE_CURRENT_USER | CERT_STORE_READONLY_FLAG, L"MY"); if(!cert_store) throw CryptoException(); while(certContext = CertFindCertificateInStore(cert_store, X509_ASN_ENCODING, 0, CERT_FIND_ANY, NULL, certContext)) { if(certificateMatchesId(certContext, id)) { DWORD key_type = 0; if (CryptAcquireCertificatePrivateKey(certContext, CRYPT_ACQUIRE_CACHE_FLAG, NULL, &cryptoProvider, &key_type, &must_release_provider)) { BYTE hashBytes[21]; DWORD hashBytesLength = 20; CryptStringToBinary(hash, VALID_HASH_LENGTH, CRYPT_STRING_HEX, hashBytes, &hashBytesLength, 0, 0); hashBytes[hashBytesLength] = '\0'; EstEID_log("Number of bytes stored in hashBytes buffer = %u", hashBytesLength); CryptoErrorHandler(CryptCreateHash(cryptoProvider, CALG_SHA1, 0, 0, &_hash)); EstEID_log("CryptCreateHash() set hash object pointer to %p", _hash); CryptoErrorHandler(CryptSetHashParam(_hash, HP_HASHVAL, hashBytes, 0)); #define SIGNATURE_LENGTH 1024 BYTE _signature[SIGNATURE_LENGTH]; DWORD signatureLength = SIGNATURE_LENGTH; INT retCode = CryptSignHash(_hash, AT_SIGNATURE, NULL, 0, _signature, &signatureLength); DWORD lastError = GetLastError(); EstEID_log("CryptSignHash() return code: %u (%s) %x", retCode, retCode ? "SUCCESS" : "FAILURE", lastError); if(!retCode) throw CryptoException(lastError); CryptDestroyHash(_hash); CryptReleaseContext(cryptoProvider, 0); CertFreeCertificateContext(certContext); if(must_release_provider) CertCloseStore(cert_store, 0); std::stringstream ss; for (DWORD i = 0; i < signatureLength; i++) { ss << std::hex << std::setfill('0') << std::setw(2) << (short)_signature[signatureLength - i - 1]; } *signature = _bstr_t(ss.str().c_str()).Detach(); } else { INT lastError = GetLastError(); EstEID_log("ERROR: CryptAcquireCertificatePrivateKey() failed, error code = %lXh", GetLastError()); switch(lastError) { case NTE_BAD_PUBLIC_KEY: EstEID_log(" error code %lXh: NTE_BAD_PUBLIC_KEY", lastError); break; case NTE_SILENT_CONTEXT: EstEID_log(" error code %lXh: NTE_SILENT_CONTEXT", lastError); } } break; } } } catch(CryptoException e) { *signature = _bstr_t("").Detach(); if(_hash) CryptDestroyHash(_hash); if(cryptoProvider) CryptReleaseContext(cryptoProvider, 0); if(certContext) CertFreeCertificateContext(certContext); if(must_release_provider && cert_store) CertCloseStore(cert_store, 0); throw(CryptoException(e.windowsErrorCode)); } }
HRESULT Hex2BstrByte( LPWSTR pwszHex, BSTR *pbstrByte) { HRESULT hr = S_OK; BSTR bstrByte = NULL; BYTE *pbData = NULL; DWORD cbData = 0; if(!pwszHex || !*pwszHex) { hr = E_INVALIDARG; goto error; } //Get buffer size first. if(!CryptStringToBinary( pwszHex, 0, CRYPT_STRING_HEX, NULL, &cbData, NULL, NULL)) { hr = E_FAIL; goto error; } pbData = (BYTE*)malloc(cbData); if(!pbData) { hr = E_OUTOFMEMORY; goto error; } //pbData points to the memory blob in which //the converted hex values are stored. if(!CryptStringToBinary( pwszHex, 0, CRYPT_STRING_HEX, pbData, &cbData, NULL, NULL)) { hr = E_FAIL; goto error; } bstrByte = SysAllocStringByteLen((LPCSTR)pbData, cbData); if(!bstrByte) { hr = E_OUTOFMEMORY; goto error; } *pbstrByte = bstrByte; error: free(pbData); return hr; }
int Base64Decode(const char *File) { #ifdef WIN32 FILE *fp = fopen(File, "rb"); long FileSize; DWORD OutFileSize = 0; char *FileContent; char *ResultContent; if( fp == NULL ) { return -1; } if( fseek(fp, 0L, SEEK_END) != 0 ) { fclose(fp); return -2; } FileSize = ftell(fp); if( FileSize < 0 ) { fclose(fp); return -3; } if( fseek(fp, 0L, SEEK_SET) != 0 ) { fclose(fp); return -4; } FileContent = SafeMalloc(FileSize); if( FileContent == NULL ) { fclose(fp); return -5; } if( fread(FileContent, 1, FileSize, fp) != FileSize ) { SafeFree(FileContent); fclose(fp); return -6; } fclose(fp); fp = fopen(File, "wb"); if( fp == NULL ) { SafeFree(FileContent); return -7; } if( CryptStringToBinary((const BYTE *)FileContent, FileSize, 0x00000001, NULL, &OutFileSize, NULL, NULL) != TRUE ) { SafeFree(FileContent); fclose(fp); return -8; } ResultContent = SafeMalloc(OutFileSize); if( ResultContent == NULL ) { SafeFree(FileContent); fclose(fp); return -9; } if( CryptStringToBinary((const BYTE *)FileContent, FileSize, 0x00000001, ResultContent, &OutFileSize, NULL, NULL) != TRUE ) { SafeFree(ResultContent); SafeFree(FileContent); fclose(fp); return -9; } fwrite(ResultContent, 1, OutFileSize, fp); SafeFree(ResultContent); SafeFree(FileContent); fclose(fp); return 0; #else /* WIN32 */ BIO *ub64, *bmem; FILE *fp = fopen(File, "rb"); long FileSize; int OutputSize = 0; char *FileContent; char *ResultContent; if( fp == NULL ) { return -1; } if( fseek(fp, 0L, SEEK_END) != 0 ) { fclose(fp); return -2; } FileSize = ftell(fp); if( FileSize < 0 ) { fclose(fp); return -3; } if( fseek(fp, 0L, SEEK_SET) != 0 ) { fclose(fp); return -4; } FileContent = SafeMalloc(FileSize); if( FileContent == NULL ) { fclose(fp); return -5; } if( fread(FileContent, 1, FileSize, fp) != FileSize ) { SafeFree(FileContent); fclose(fp); return -6; } fclose(fp); ub64 = BIO_new(BIO_f_base64()); if( ub64 == NULL ) { SafeFree(FileContent); return -7; } bmem = BIO_new_mem_buf(FileContent, FileSize); if( ub64 == NULL ) { SafeFree(FileContent); return -8; } fp = fopen(File, "wb"); if( fp == NULL ) { BIO_free_all(bmem); SafeFree(FileContent); return -9; } bmem = BIO_push(ub64, bmem); if( bmem== NULL ) { SafeFree(FileContent); fclose(fp); return -10; } ResultContent = SafeMalloc(FileSize); if( ResultContent == NULL ) { BIO_free_all(bmem); SafeFree(FileContent); fclose(fp); return -11; } OutputSize = BIO_read(bmem, ResultContent, FileSize); if( OutputSize < 1 ) { BIO_free_all(bmem); SafeFree(ResultContent); SafeFree(FileContent); fclose(fp); return -12; } fwrite(ResultContent, 1, OutputSize, fp); BIO_free_all(bmem); SafeFree(ResultContent); SafeFree(FileContent); fclose(fp); return 0; #endif /* WIN32 */ }