/////////////////////////////////////////////////////////////////////////////////////// // Function: GetRSAKeyFromCert // Description: RSA key fetching from the cert /////////////////////////////////////////////////////////////////////////////////////// BOOL GetRSAKeyFromCert( /////////////////////////////////////////////////////////////////////////////////////// PCCERT_CONTEXT pCertContext, HCRYPTPROV *hProv, HCRYPTKEY *hPubKey, DWORD *dwKeySpec, BOOL *fFreeProv) { BOOL fResult; BOOL fReturn = FALSE; __try { if (hProv == NULL || hPubKey == NULL || dwKeySpec == NULL || fFreeProv == NULL) { __leave; } *hProv = NULL; *hPubKey = NULL; *fFreeProv = FALSE; fResult = CryptAcquireCertificatePrivateKey(pCertContext, NULL, NULL, hProv, dwKeySpec, fFreeProv); if (!fResult) { __leave; } fReturn = TRUE; } __finally { if (!fReturn) { if (*hPubKey != NULL) { CryptDestroyKey(*hPubKey); *hPubKey = NULL; } if ((*fFreeProv == TRUE) && (*hProv != NULL)) { CryptReleaseContext(*hProv, 0); *hProv = NULL; *fFreeProv = FALSE; } } } return fReturn; }
BOOL isCardInReader(PCCERT_CONTEXT certContext) { #ifndef WIN_XP DWORD flags = CRYPT_ACQUIRE_CACHE_FLAG|CRYPT_ACQUIRE_COMPARE_KEY_FLAG|CRYPT_ACQUIRE_SILENT_FLAG; NCRYPT_KEY_HANDLE key = 0; DWORD spec = 0; BOOL ncrypt = FALSE; CryptAcquireCertificatePrivateKey(certContext, flags, 0, &key, &spec, &ncrypt); if(!key) { return FALSE; } if(ncrypt) { NCryptFreeObject(key); } #endif return TRUE; }
/***************************************************************************** HrGetSignerKeyAndChain This function retrieves a signing certificate from the local user’s certificate store, builds certificates chain and returns key handle for the signing key.” NOTE: The phCryptProvOrNCryptKey is cached and must not be released by the caller. *****************************************************************************/ static HRESULT HrGetSignerKeyAndChain( LPCWSTR wszSubject, PCCERT_CHAIN_CONTEXT *ppChainContext, HCRYPTPROV_OR_NCRYPT_KEY_HANDLE* phCryptProvOrNCryptKey, DWORD *pdwKeySpec ) { HRESULT hr = S_FALSE; HCERTSTORE hStore = NULL; PCCERT_CONTEXT pCert = NULL; BOOL fCallerFreeProvOrNCryptKey = FALSE; CERT_CHAIN_PARA ChainPara = {0}; ChainPara.cbSize = sizeof(ChainPara); *ppChainContext = NULL; *phCryptProvOrNCryptKey = NULL; *pdwKeySpec = 0; // // Open the local user store to search for certificates // hStore = CertOpenStore( CERT_STORE_PROV_SYSTEM_W, X509_ASN_ENCODING, NULL, CERT_SYSTEM_STORE_CURRENT_USER | CERT_STORE_DEFER_CLOSE_UNTIL_LAST_FREE_FLAG, L"MY" ); if( NULL == hStore ) { hr = HRESULT_FROM_WIN32( GetLastError() ); goto CleanUp; } if( NULL != wszSubject && 0 != *wszSubject ) { // // Search by Name // while( NULL != ( pCert = CertFindCertificateInStore( hStore, X509_ASN_ENCODING, 0, CERT_FIND_SUBJECT_STR, wszSubject, pCert ))) { if( CryptAcquireCertificatePrivateKey( pCert, CRYPT_ACQUIRE_CACHE_FLAG, NULL, phCryptProvOrNCryptKey, pdwKeySpec, &fCallerFreeProvOrNCryptKey )) { break; } } } else { // // Get the first available certificate in the store // while( NULL != ( pCert = CertEnumCertificatesInStore( hStore, pCert ))) { if( CryptAcquireCertificatePrivateKey( pCert, CRYPT_ACQUIRE_CACHE_FLAG, NULL, phCryptProvOrNCryptKey, pdwKeySpec, &fCallerFreeProvOrNCryptKey )) { break; } } } if( NULL == pCert ) { hr = CRYPT_XML_E_SIGNER; goto CleanUp; } // // Build the certificate chain without revocation check. // if( !CertGetCertificateChain( NULL, // use the default chain engine pCert, // pointer to the end certificate NULL, // use the default time NULL, // search no additional stores &ChainPara, 0, // no revocation check NULL, // currently reserved ppChainContext )) // return a pointer to the chain created { hr = HRESULT_FROM_WIN32( GetLastError() ); goto CleanUp; } CleanUp: if( FAILED(hr) ) { *phCryptProvOrNCryptKey = NULL; *pdwKeySpec = 0; } if( NULL != pCert ) { CertFreeCertificateContext( pCert ); } if( NULL != hStore ) { CertCloseStore( hStore, 0 ); } return hr; }
DWORD do_low_sign (const char *infile, const char *outfile) { char OID[64] = szOID_CP_GOST_R3411; int include = 1; HCRYPTPROV hCryptProv = 0; // CSP handle PCCERT_CONTEXT pUserCert = NULL; // User certificate to be used DWORD keytype = 0; CSP_BOOL should_release_ctx = FALSE; DWORD ret = 1; FILE *tbs = NULL; BYTE *mem_tbs = NULL; DWORD mem_len = 0; HCRYPTMSG hMsg = 0; DWORD HashAlgSize; DWORD dwSize; CRYPT_ALGORITHM_IDENTIFIER HashAlgorithm; CMSG_SIGNER_ENCODE_INFO SignerEncodeInfo; CERT_BLOB SignerCertBlob; CERT_BLOB SignerCertBlobArray[1]; DWORD cbEncodedBlob; BYTE *pbEncodedBlob = NULL; CMSG_SIGNER_ENCODE_INFO SignerEncodeInfoArray[1]; CMSG_SIGNED_ENCODE_INFO SignedMsgEncodeInfo; CSP_BOOL bResult = FALSE; CRYPT_KEY_PROV_INFO *pProvInfo = NULL; HCERTSTORE hCertStore = 0; hCertStore = CertOpenSystemStore(0, "My"); if(!hCertStore){ ret = CSP_GetLastError(); fprintf (stderr, "CertOpenSystemStore failed."); goto err; } while( !bResult){ pUserCert= CertEnumCertificatesInStore(hCertStore, pUserCert); if(!pUserCert){ break; } bResult = CertGetCertificateContextProperty( pUserCert, CERT_KEY_PROV_INFO_PROP_ID, NULL, &dwSize); if (bResult) { free(pProvInfo); pProvInfo = (CRYPT_KEY_PROV_INFO *)malloc(dwSize); if (pProvInfo) { bResult = CertGetCertificateContextProperty( pUserCert, CERT_KEY_PROV_INFO_PROP_ID, pProvInfo, &dwSize); } } } if(!bResult){ fprintf (stderr, "No certificates with private key link."); goto err; } if (! infile) { fprintf (stderr, "No input file was specified\n"); goto err; } if (CryptAcquireCertificatePrivateKey( pUserCert, 0, //DWORD dwFlags, NULL, &hCryptProv, &keytype, // returned key type AT_SIGNATURE ! AT_KEYEXCAHGE &should_release_ctx // if FALSE DO NOT Release CTX )) { printf("A CSP has been acquired. \n"); } else { ret = CSP_GetLastError(); fprintf (stderr, "Cryptographic context could not be acquired."); goto err; } tbs = fopen (infile, "rb"); if (!tbs) { fprintf (stderr, "Cannot open input file\n"); goto err; } mem_len = 0; while (!feof(tbs)) { int r = 0; BYTE tmp[1024]; r = fread (tmp, 1, 1024, tbs); mem_tbs = (BYTE *)realloc(mem_tbs, mem_len+r); memcpy (&mem_tbs[mem_len], tmp, r); mem_len += r; } fclose (tbs); tbs = NULL; //-------------------------------------------------------------------- // Initialize the algorithm identifier structure. HashAlgSize = sizeof(HashAlgorithm); memset(&HashAlgorithm, 0, HashAlgSize); // Init. to zero. HashAlgorithm.pszObjId = OID; // Initialize the necessary member. //-------------------------------------------------------------------- // Initialize the CMSG_SIGNER_ENCODE_INFO structure. memset(&SignerEncodeInfo, 0, sizeof(CMSG_SIGNER_ENCODE_INFO)); SignerEncodeInfo.cbSize = sizeof(CMSG_SIGNER_ENCODE_INFO); SignerEncodeInfo.pCertInfo = pUserCert->pCertInfo; SignerEncodeInfo.hCryptProv = hCryptProv; SignerEncodeInfo.dwKeySpec = keytype; SignerEncodeInfo.HashAlgorithm = HashAlgorithm; SignerEncodeInfo.pvHashAuxInfo = NULL; //-------------------------------------------------------------------- // Create an array of one. Note: Currently, there can be only one // signer. SignerEncodeInfoArray[0] = SignerEncodeInfo; //-------------------------------------------------------------------- // Initialize the CMSG_SIGNED_ENCODE_INFO structure. SignerCertBlob.cbData = pUserCert->cbCertEncoded; SignerCertBlob.pbData = pUserCert->pbCertEncoded; //-------------------------------------------------------------------- // Initialize the array of one CertBlob. SignerCertBlobArray[0] = SignerCertBlob; memset(&SignedMsgEncodeInfo, 0, sizeof(CMSG_SIGNED_ENCODE_INFO)); SignedMsgEncodeInfo.cbSize = sizeof(CMSG_SIGNED_ENCODE_INFO); SignedMsgEncodeInfo.cSigners = 1; SignedMsgEncodeInfo.rgSigners = SignerEncodeInfoArray; SignedMsgEncodeInfo.cCertEncoded = include; if (include) SignedMsgEncodeInfo.rgCertEncoded = SignerCertBlobArray; else SignedMsgEncodeInfo.rgCertEncoded = NULL; SignedMsgEncodeInfo.rgCrlEncoded = NULL; //-------------------------------------------------------------------- // Get the size of the encoded message blob. if(cbEncodedBlob = CryptMsgCalculateEncodedLength( TYPE_DER, // Message encoding type 0, // Flags CMSG_SIGNED, // Message type &SignedMsgEncodeInfo, // Pointer to structure NULL, // Inner content object ID mem_len)) // Size of content */ { printf("The length of the data has been calculated. \n"); } else { ret = CSP_GetLastError(); fprintf (stderr, "Getting cbEncodedBlob length failed"); goto err; } //-------------------------------------------------------------------- // Allocate memory for the encoded blob. pbEncodedBlob = (BYTE *) malloc(cbEncodedBlob); if (!pbEncodedBlob){ ret = CSP_GetLastError(); fprintf (stderr, "Memory allocation failed"); goto err; } //-------------------------------------------------------------------- // Open a message to encode. if(hMsg = CryptMsgOpenToEncode( TYPE_DER, // Encoding type 0, // Flags CMSG_SIGNED, // Message type &SignedMsgEncodeInfo, // Pointer to structure NULL, // Inner content object ID NULL)) // Stream information (not used) { printf("The message to be encoded has been opened. \n"); } else { ret = CSP_GetLastError(); fprintf (stderr, "OpenToEncode failed"); goto err; } //-------------------------------------------------------------------- // Update the message with the data. if(CryptMsgUpdate( hMsg, // Handle to the message mem_tbs, // Pointer to the content mem_len, // Size of the content TRUE)) // Last call { printf("Content has been added to the encoded message. \n"); } else { ret = CSP_GetLastError(); fprintf (stderr, "MsgUpdate failed"); goto err; } //-------------------------------------------------------------------- // Get the resulting message. if(CryptMsgGetParam( hMsg, // Handle to the message CMSG_CONTENT_PARAM, // Parameter type 0, // Index pbEncodedBlob, // Pointer to the blob &cbEncodedBlob)) // Size of the blob { printf("Message encoded successfully. \n"); } else { ret = CSP_GetLastError(); fprintf (stderr, "MsgGetParam failed"); goto err; } //-------------------------------------------------------------------- // pbEncodedBlob now points to the encoded, signed content. //-------------------------------------------------------------------- if (outfile) { FILE *out = NULL; out = fopen (outfile, "wb"); if (out) { fwrite (pbEncodedBlob, cbEncodedBlob, 1, out); fclose (out); printf ("Output file (%s) has been saved\n", outfile); } else perror ("Cannot open out file\n"); } ret = 0; //-------------------------------------------------------------------- // Clean up. err: if(pbEncodedBlob) free(pbEncodedBlob); if(hMsg) CryptMsgClose(hMsg); if(hCryptProv) CryptReleaseContext(hCryptProv,0); if(hCertStore) CertCloseStore(hCertStore, 0); return ret; }
static int HCSP_setContext(void) { int result = TRUE; LPSTR a = NULL; LPSTR b = NULL; LPSTR c = "My"; #ifdef DEBUG BIO_printf(err, "Call HCSP_setContext()\n"); #endif #ifdef FILE_CONFIG readFileConfig(); /* get specified context provider, etc... */ if (pCryptProvider[0] && strcasecmp(pCryptProvider, "default")) a = pCryptProvider; if (pCryptContainer[0] && strcasecmp(pCryptContainer, "default")) b = pCryptContainer; if (pSubsystemProtocol[0] && strcasecmp(pSubsystemProtocol, "default")) c = pSubsystemProtocol; #endif #ifdef DEBUG strcpy(pSubsystemProtocol, c); BIO_printf(err, "Call HCSP_setContext()\n"); BIO_printf(err, "pCryptProvider: \"%s\"\n", a); BIO_printf(err, "dwProviderType: %d\n", dwProviderType); BIO_printf(err, "pCryptContainer: \"%s\"\n", b); BIO_printf(err, "pSubsystemProtocol: \"%s\"\n", c); BIO_printf(err, "pFindPara: \"%s\"\n", pFindPara); #endif /* * Set hCryptProvider to NULL to use the default CSP. If hCryptProvider is not NULL, * it must be a CSP handle created by using the CryptAcquireContext function. */ if (!(hCertStore = CertOpenSystemStore(hCryptProvider, c))) { # ifdef DEBUG routine = "CertOpenSystemStore"; # endif goto error; } #ifdef DEBUG enumCertificate(); #endif if (!(pCertContext = CertFindCertificateInStore( hCertStore, (PKCS_7_ASN_ENCODING | X509_ASN_ENCODING), 0, CERT_FIND_SUBJECT_STR_A, pFindPara, NULL))) { # ifdef DEBUG routine = "CertFindCertificateInStore"; # endif goto error; } if (!CryptAcquireCertificatePrivateKey( pCertContext, 0, NULL, &hCryptProvider, &dwKeySpec, NULL)) { # ifdef DEBUG routine = "CryptAcquireCertificatePrivateKey"; # endif goto error; } #ifdef DEBUG printInfo(); enumKeyContainers(); enumAlgorithms(); printCertificate(pCertContext); #endif bInitialized = TRUE; /* set initialization flag */ goto end; error: result = FALSE; end: #ifdef DEBUG BIO_printf(err, "Return HCSP_setContext(%d)\n", result); #endif return result; }
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)); } }
BOOL AcquireAndGetRSAKey(PCCERT_CONTEXT pCertContext, HCRYPTPROV *phProv, HCRYPTKEY *phRSAKey, BOOL fEncrypt, BOOL *pfCallerFreeProv) { BOOL fSuccess = FALSE; DWORD dwKeySpec = 0; __try { *phProv = NULL; *phRSAKey = NULL; *pfCallerFreeProv = FALSE; if (fEncrypt) { // Acquire context for RSA key fSuccess = CryptAcquireContext(phProv, NULL, MS_DEF_PROV, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT); if (!fSuccess) { MyPrintf(_T("CryptAcquireContext failed with %X\n"), GetLastError()); __leave; } // Import the RSA public key from the certificate context fSuccess = CryptImportPublicKeyInfo(*phProv, MY_ENCODING, &(pCertContext->pCertInfo->SubjectPublicKeyInfo), phRSAKey); if (!fSuccess) { MyPrintf(_T("CryptImportPublicKeyInfo failed with %X\n"), GetLastError()); __leave; } *pfCallerFreeProv = TRUE; } else { // Acquire the RSA private key fSuccess = CryptAcquireCertificatePrivateKey(pCertContext, CRYPT_ACQUIRE_USE_PROV_INFO_FLAG|CRYPT_ACQUIRE_COMPARE_KEY_FLAG, NULL, phProv, &dwKeySpec, pfCallerFreeProv); if (!fSuccess) { MyPrintf(_T("CryptAcquireCertificatePrivateKey failed with %X\n"), GetLastError()); __leave; } // Get the RSA key handle fSuccess = CryptGetUserKey(*phProv, dwKeySpec, phRSAKey); if (!fSuccess) { MyPrintf(_T("CryptGetUserKey failed with %X\n"), GetLastError()); __leave; } } } __finally { if (fSuccess == FALSE) { if (phProv && *phProv != NULL) { CryptReleaseContext(*phProv, 0); *phProv = NULL; } if (phRSAKey && *phRSAKey != NULL) { CryptDestroyKey(*phRSAKey); *phRSAKey = NULL; } } } return fSuccess; }
BYTE* SignAndEncrypt( wchar_t const*const signer_name, const BYTE *pbToBeSignedAndEncrypted, DWORD cbToBeSignedAndEncrypted, DWORD *pcbSignedAndEncryptedBlob) { //--------------------------------------------------------------- // Declare and initialize local variables. FILE *hToSave; HCERTSTORE hCertStore; //--------------------------------------------------------------- // pSignerCertContext will be the certificate of // the message signer. PCCERT_CONTEXT pSignerCertContext ; //--------------------------------------------------------------- // pReceiverCertContext will be the certificate of the // message receiver. PCCERT_CONTEXT pReceiverCertContext; TCHAR pszNameString[256]; CRYPT_SIGN_MESSAGE_PARA SignPara; CRYPT_ENCRYPT_MESSAGE_PARA EncryptPara; DWORD cRecipientCert; PCCERT_CONTEXT rgpRecipientCert[5]; BYTE *pbSignedAndEncryptedBlob = NULL; //CERT_NAME_BLOB Subject_Blob; BYTE *pbDataIn; DWORD dwKeySpec; NCRYPT_KEY_HANDLE hCryptProv; //--------------------------------------------------------------- // Open the MY certificate store. // For more information, see the CertOpenStore function // PSDK reference page. // Note: Case is not significant in certificate store names. if ( !( hCertStore = CertOpenStore( CERT_STORE_PROV_SYSTEM, 0, NULL, CERT_SYSTEM_STORE_CURRENT_USER, L"my"))) { MyHandleError(TEXT("The MY store could not be opened.")); } //--------------------------------------------------------------- // Get the certificate for the signer. if(!(pSignerCertContext = CertFindCertificateInStore( hCertStore, MY_ENCODING_TYPE, 0, CERT_FIND_SUBJECT_STR, signer_name, NULL))) { MyHandleError(TEXT("Cert not found.\n")); } //--------------------------------------------------------------- // Get and print the name of the message signer. // The following two calls to CertGetNameString with different // values for the second parameter get two different forms of // the certificate subject's name. if(CertGetNameString( pSignerCertContext , CERT_NAME_SIMPLE_DISPLAY_TYPE, 0, NULL, pszNameString, MAX_NAME) > 1) { _tprintf( TEXT("The SIMPLE_DISPLAY_TYPE message signer's name is ") TEXT("%s \n"), pszNameString); } else { MyHandleError( TEXT("Getting the name of the signer failed.\n")); } if(CertGetNameString( pSignerCertContext, CERT_NAME_RDN_TYPE, 0, NULL, pszNameString, MAX_NAME) > 1) { _tprintf( TEXT("The RDM_TYPE message signer's name is %s \n"), pszNameString); } else { MyHandleError( TEXT("Getting the name of the signer failed.\n")); } if(!( CryptAcquireCertificatePrivateKey( pSignerCertContext, CRYPT_ACQUIRE_ONLY_NCRYPT_KEY_FLAG, NULL, &hCryptProv, &dwKeySpec, NULL))) { DWORD const errcode = GetLastError(); std::wcerr << format_sys_message<TCHAR>(errcode) << TEXT("\n"); MyHandleError(TEXT("CryptAcquireCertificatePrivateKey.\n")); } pReceiverCertContext = pSignerCertContext; // send to self //--------------------------------------------------------------- // Get and print the subject name from the receiver's // certificate. if(CertGetNameString( pReceiverCertContext , CERT_NAME_SIMPLE_DISPLAY_TYPE, 0, NULL, pszNameString, MAX_NAME) > 1) { _tprintf(TEXT("The message receiver is %s \n"), pszNameString); } else { MyHandleError( TEXT("Getting the name of the receiver failed.\n")); } //--------------------------------------------------------------- // Initialize variables and data structures // for the call to CryptSignAndEncryptMessage. SignPara.cbSize = sizeof(CRYPT_SIGN_MESSAGE_PARA); SignPara.dwMsgEncodingType = MY_ENCODING_TYPE; SignPara.pSigningCert = pSignerCertContext ; SignPara.HashAlgorithm.pszObjId = OID_HASH_G34311; SignPara.HashAlgorithm.Parameters.cbData = 0; SignPara.pvHashAuxInfo = NULL; SignPara.cMsgCert = 1; SignPara.rgpMsgCert = &pSignerCertContext ; SignPara.cMsgCrl = 0; SignPara.rgpMsgCrl = NULL; SignPara.cAuthAttr = 0; SignPara.rgAuthAttr = NULL; SignPara.cUnauthAttr = 0; SignPara.rgUnauthAttr = NULL; SignPara.dwFlags = 0; SignPara.dwInnerContentType = 0; EncryptPara.cbSize = sizeof(CRYPT_ENCRYPT_MESSAGE_PARA); EncryptPara.dwMsgEncodingType = MY_ENCODING_TYPE; EncryptPara.hCryptProv = 0; EncryptPara.ContentEncryptionAlgorithm.pszObjId = OID_G28147_89_GAMMA_CBC; //szOID_RSA_RC4; EncryptPara.ContentEncryptionAlgorithm.Parameters.cbData = 0; EncryptPara.pvEncryptionAuxInfo = NULL; EncryptPara.dwFlags = 0; EncryptPara.dwInnerContentType = 0; cRecipientCert = 1; rgpRecipientCert[0] = pReceiverCertContext; *pcbSignedAndEncryptedBlob = 0; pbSignedAndEncryptedBlob = NULL; if( CryptSignAndEncryptMessage( &SignPara, &EncryptPara, cRecipientCert, rgpRecipientCert, pbToBeSignedAndEncrypted, cbToBeSignedAndEncrypted, NULL, // the pbSignedAndEncryptedBlob pcbSignedAndEncryptedBlob)) { _tprintf(TEXT("%d bytes for the buffer .\n"), *pcbSignedAndEncryptedBlob); } else { DWORD const errcode = GetLastError(); std::wcerr << format_sys_message<TCHAR>(errcode) << TEXT("\n"); MyHandleError(TEXT("Getting the buffer length failed.")); } //--------------------------------------------------------------- // Allocate memory for the buffer. if(!(pbSignedAndEncryptedBlob = (unsigned char *)malloc(*pcbSignedAndEncryptedBlob))) { MyHandleError(TEXT("Memory allocation failed.")); } //--------------------------------------------------------------- // Call the function a second time to copy the signed and // encrypted message into the buffer. if( CryptSignAndEncryptMessage( &SignPara, &EncryptPara, cRecipientCert, rgpRecipientCert, pbToBeSignedAndEncrypted, cbToBeSignedAndEncrypted, pbSignedAndEncryptedBlob, pcbSignedAndEncryptedBlob)) { _tprintf(TEXT("The message is signed and encrypted.\n")); } else { MyHandleError( TEXT("The message failed to sign and encrypt.")); } //--------------------------------------------------------------- // Clean up. if(pSignerCertContext ) { CertFreeCertificateContext(pSignerCertContext); } // send to self so the same cert is used // if(pReceiverCertContext ) // { // CertFreeCertificateContext(pReceiverCertContext); // } CertCloseStore(hCertStore, 0); //--------------------------------------------------------------- // Return the signed and encrypted message. return pbSignedAndEncryptedBlob; } // End SignAndEncrypt.
NTSTATUS kuhl_m_crypto_l_certificates(int argc, wchar_t * argv[]) { HCERTSTORE hCertificateStore; PCCERT_CONTEXT pCertContext; DWORD i, j, dwSizeNeeded, keySpec; wchar_t *certName; PCRYPT_KEY_PROV_INFO pBuffer; HCRYPTPROV_OR_NCRYPT_KEY_HANDLE monProv; HCRYPTKEY maCle; BOOL keyToFree; PCWCHAR szSystemStore, szStore; DWORD dwSystemStore = 0; BOOL export = kull_m_string_args_byName(argc, argv, L"export", NULL, NULL); kull_m_string_args_byName(argc, argv, L"systemstore", &szSystemStore, kuhl_m_crypto_system_stores[0].name); dwSystemStore = kuhl_m_crypto_system_store_to_dword(szSystemStore); kull_m_string_args_byName(argc, argv, L"store", &szStore, L"My"); kprintf(L" * System Store : \'%s\' (0x%08x)\n" L" * Store : \'%s\'\n\n", szSystemStore, dwSystemStore, szStore); if(hCertificateStore = CertOpenStore(CERT_STORE_PROV_SYSTEM, 0, (HCRYPTPROV_LEGACY) NULL, dwSystemStore | CERT_STORE_OPEN_EXISTING_FLAG | CERT_STORE_READONLY_FLAG, szStore)) { for (i = 0, pCertContext = CertEnumCertificatesInStore(hCertificateStore, NULL); pCertContext != NULL; pCertContext = CertEnumCertificatesInStore(hCertificateStore, pCertContext), i++) { for(j = 0; j < ARRAYSIZE(nameSrc); j++) { dwSizeNeeded = CertGetNameString(pCertContext, nameSrc[j], 0, NULL, NULL, 0); if(dwSizeNeeded > 0) { if(certName = (wchar_t *) LocalAlloc(LPTR, dwSizeNeeded * sizeof(wchar_t))) { if(CertGetNameString(pCertContext, nameSrc[j], 0, NULL, certName, dwSizeNeeded) == dwSizeNeeded) { kprintf(L"%2u. %s\n", i, certName); dwSizeNeeded = 0; if(CertGetCertificateContextProperty(pCertContext, CERT_KEY_PROV_INFO_PROP_ID, NULL, &dwSizeNeeded)) { if(pBuffer = (PCRYPT_KEY_PROV_INFO) LocalAlloc(LPTR, dwSizeNeeded)) { if(CertGetCertificateContextProperty(pCertContext, CERT_KEY_PROV_INFO_PROP_ID, pBuffer, &dwSizeNeeded)) { kprintf( L"\tKey Container : %s\n" L"\tProvider : %s\n", (pBuffer->pwszContainerName ? pBuffer->pwszContainerName : L"(null)"), (pBuffer->pwszProvName ? pBuffer->pwszProvName : L"(null)")); if(CryptAcquireCertificatePrivateKey(pCertContext, CRYPT_ACQUIRE_ALLOW_NCRYPT_KEY_FLAG /* CRYPT_ACQUIRE_SILENT_FLAG NULL */, NULL, &monProv, &keySpec, &keyToFree)) { kprintf(L"\tType : %s (0x%08x)\n", kuhl_m_crypto_keytype_to_str(keySpec), keySpec); if(keySpec != CERT_NCRYPT_KEY_SPEC) { if(CryptGetUserKey(monProv, keySpec, &maCle)) { kuhl_m_crypto_printKeyInfos(0, maCle); CryptDestroyKey(maCle); } else PRINT_ERROR_AUTO(L"CryptGetUserKey"); if(keyToFree) CryptReleaseContext(monProv, 0); } else if(kuhl_m_crypto_hNCrypt) { kuhl_m_crypto_printKeyInfos(monProv, 0); if(keyToFree) K_NCryptFreeObject(monProv); } else PRINT_ERROR(L"keySpec == CERT_NCRYPT_KEY_SPEC without CNG Handle ?\n"); } else PRINT_ERROR_AUTO(L"CryptAcquireCertificatePrivateKey"); } else PRINT_ERROR_AUTO(L"CertGetCertificateContextProperty"); } LocalFree(pBuffer); if(!export) kprintf(L"\n"); } if(export) kuhl_m_crypto_exportCert(pCertContext, (BOOL) dwSizeNeeded, szSystemStore, szStore, i, certName); } else PRINT_ERROR_AUTO(L"CertGetNameString"); LocalFree(certName); } break; } else PRINT_ERROR_AUTO(L"CertGetNameString (for len)"); }
int SSL_CTX_use_CryptoAPI_certificate(SSL_CTX *ssl_ctx, const char *cert_prop) { HCERTSTORE cs; X509 *cert = NULL; RSA *rsa = NULL, *pub_rsa; CAPI_DATA *cd = calloc(1, sizeof(*cd)); RSA_METHOD *my_rsa_method = calloc(1, sizeof(*my_rsa_method)); if (cd == NULL || my_rsa_method == NULL) { SSLerr(SSL_F_SSL_CTX_USE_CERTIFICATE_FILE, ERR_R_MALLOC_FAILURE); goto err; } /* search CURRENT_USER first, then LOCAL_MACHINE */ cs = CertOpenStore((LPCSTR) CERT_STORE_PROV_SYSTEM, 0, 0, CERT_SYSTEM_STORE_CURRENT_USER | CERT_STORE_OPEN_EXISTING_FLAG | CERT_STORE_READONLY_FLAG, L"MY"); if (cs == NULL) { CRYPTOAPIerr(CRYPTOAPI_F_CERT_OPEN_SYSTEM_STORE); goto err; } cd->cert_context = find_certificate_in_store(cert_prop, cs); CertCloseStore(cs, 0); if (!cd->cert_context) { cs = CertOpenStore((LPCSTR) CERT_STORE_PROV_SYSTEM, 0, 0, CERT_SYSTEM_STORE_LOCAL_MACHINE | CERT_STORE_OPEN_EXISTING_FLAG | CERT_STORE_READONLY_FLAG, L"MY"); if (cs == NULL) { CRYPTOAPIerr(CRYPTOAPI_F_CERT_OPEN_SYSTEM_STORE); goto err; } cd->cert_context = find_certificate_in_store(cert_prop, cs); CertCloseStore(cs, 0); if (cd->cert_context == NULL) { CRYPTOAPIerr(CRYPTOAPI_F_CERT_FIND_CERTIFICATE_IN_STORE); goto err; } } /* cert_context->pbCertEncoded is the cert X509 DER encoded. */ cert = d2i_X509(NULL, (unsigned char **) &cd->cert_context->pbCertEncoded, cd->cert_context->cbCertEncoded); if (cert == NULL) { SSLerr(SSL_F_SSL_CTX_USE_CERTIFICATE_FILE, ERR_R_ASN1_LIB); goto err; } /* set up stuff to use the private key */ #ifdef __MINGW32_VERSION /* MinGW w32api is incomplete when it comes to CryptoAPI, as per version 3.1 * anyway. This is a hack around that problem. */ if (crypt32dll == NULL) { crypt32dll = LoadLibrary("crypt32"); if (crypt32dll == NULL) { CRYPTOAPIerr(CRYPTOAPI_F_LOAD_LIBRARY); goto err; } } if (CryptAcquireCertificatePrivateKey == NULL) { CryptAcquireCertificatePrivateKey = GetProcAddress(crypt32dll, "CryptAcquireCertificatePrivateKey"); if (CryptAcquireCertificatePrivateKey == NULL) { CRYPTOAPIerr(CRYPTOAPI_F_GET_PROC_ADDRESS); goto err; } } #endif if (!CryptAcquireCertificatePrivateKey(cd->cert_context, CRYPT_ACQUIRE_COMPARE_KEY_FLAG, NULL, &cd->crypt_prov, &cd->key_spec, &cd->free_crypt_prov)) { /* if we don't have a smart card reader here, and we try to access a * smart card certificate, we get: * "Error 1223: The operation was canceled by the user." */ CRYPTOAPIerr(CRYPTOAPI_F_CRYPT_ACQUIRE_CERTIFICATE_PRIVATE_KEY); goto err; } /* here we don't need to do CryptGetUserKey() or anything; all necessary key * info is in cd->cert_context, and then, in cd->crypt_prov. */ my_rsa_method->name = "Microsoft CryptoAPI RSA Method"; my_rsa_method->rsa_pub_enc = rsa_pub_enc; my_rsa_method->rsa_pub_dec = rsa_pub_dec; my_rsa_method->rsa_priv_enc = rsa_priv_enc; my_rsa_method->rsa_priv_dec = rsa_priv_dec; /* my_rsa_method->init = init; */ my_rsa_method->finish = finish; my_rsa_method->flags = RSA_METHOD_FLAG_NO_CHECK; my_rsa_method->app_data = (char *) cd; rsa = RSA_new(); if (rsa == NULL) { SSLerr(SSL_F_SSL_CTX_USE_CERTIFICATE_FILE, ERR_R_MALLOC_FAILURE); goto err; } /* cert->cert_info->key->pkey is NULL until we call SSL_CTX_use_certificate(), * so we do it here then... */ if (!SSL_CTX_use_certificate(ssl_ctx, cert)) goto err; /* the public key */ pub_rsa = cert->cert_info->key->pkey->pkey.rsa; /* SSL_CTX_use_certificate() increased the reference count in 'cert', so * we decrease it here with X509_free(), or it will never be cleaned up. */ X509_free(cert); cert = NULL; /* I'm not sure about what we have to fill in in the RSA, trying out stuff... */ /* rsa->n indicates the key size */ rsa->n = BN_dup(pub_rsa->n); rsa->flags |= RSA_FLAG_EXT_PKEY; if (!RSA_set_method(rsa, my_rsa_method)) goto err; if (!SSL_CTX_use_RSAPrivateKey(ssl_ctx, rsa)) goto err; /* SSL_CTX_use_RSAPrivateKey() increased the reference count in 'rsa', so * we decrease it here with RSA_free(), or it will never be cleaned up. */ RSA_free(rsa); return 1; err: if (cert) X509_free(cert); if (rsa) RSA_free(rsa); else { if (my_rsa_method) free(my_rsa_method); if (cd) { if (cd->free_crypt_prov && cd->crypt_prov) CryptReleaseContext(cd->crypt_prov, 0); if (cd->cert_context) CertFreeCertificateContext(cd->cert_context); free(cd); } } return 0; }
BOOL WINAPI CryptSignMessage(PCRYPT_SIGN_MESSAGE_PARA pSignPara, BOOL fDetachedSignature, DWORD cToBeSigned, const BYTE *rgpbToBeSigned[], DWORD rgcbToBeSigned[], BYTE *pbSignedBlob, DWORD *pcbSignedBlob) { HCRYPTPROV hCryptProv; BOOL ret, freeProv = FALSE; DWORD i, keySpec; PCERT_BLOB certBlob = NULL; PCRL_BLOB crlBlob = NULL; CMSG_SIGNED_ENCODE_INFO signInfo; CMSG_SIGNER_ENCODE_INFO signer; HCRYPTMSG msg = 0; TRACE("(%p, %d, %d, %p, %p, %p, %p)\n", pSignPara, fDetachedSignature, cToBeSigned, rgpbToBeSigned, rgcbToBeSigned, pbSignedBlob, pcbSignedBlob); if (pSignPara->cbSize != sizeof(CRYPT_SIGN_MESSAGE_PARA) || GET_CMSG_ENCODING_TYPE(pSignPara->dwMsgEncodingType) != PKCS_7_ASN_ENCODING) { *pcbSignedBlob = 0; SetLastError(E_INVALIDARG); return FALSE; } if (!pSignPara->pSigningCert) return TRUE; ret = CryptAcquireCertificatePrivateKey(pSignPara->pSigningCert, CRYPT_ACQUIRE_CACHE_FLAG, NULL, &hCryptProv, &keySpec, &freeProv); if (!ret) return FALSE; memset(&signer, 0, sizeof(signer)); signer.cbSize = sizeof(signer); signer.pCertInfo = pSignPara->pSigningCert->pCertInfo; signer.hCryptProv = hCryptProv; signer.dwKeySpec = keySpec; signer.HashAlgorithm = pSignPara->HashAlgorithm; signer.pvHashAuxInfo = pSignPara->pvHashAuxInfo; signer.cAuthAttr = pSignPara->cAuthAttr; signer.rgAuthAttr = pSignPara->rgAuthAttr; signer.cUnauthAttr = pSignPara->cUnauthAttr; signer.rgUnauthAttr = pSignPara->rgUnauthAttr; memset(&signInfo, 0, sizeof(signInfo)); signInfo.cbSize = sizeof(signInfo); signInfo.cSigners = 1; signInfo.rgSigners = &signer; if (pSignPara->cMsgCert) { certBlob = CryptMemAlloc(sizeof(CERT_BLOB) * pSignPara->cMsgCert); if (certBlob) { for (i = 0; i < pSignPara->cMsgCert; ++i) { certBlob[i].cbData = pSignPara->rgpMsgCert[i]->cbCertEncoded; certBlob[i].pbData = pSignPara->rgpMsgCert[i]->pbCertEncoded; } signInfo.cCertEncoded = pSignPara->cMsgCert; signInfo.rgCertEncoded = certBlob; } else ret = FALSE; } if (pSignPara->cMsgCrl) { crlBlob = CryptMemAlloc(sizeof(CRL_BLOB) * pSignPara->cMsgCrl); if (crlBlob) { for (i = 0; i < pSignPara->cMsgCrl; ++i) { crlBlob[i].cbData = pSignPara->rgpMsgCrl[i]->cbCrlEncoded; crlBlob[i].pbData = pSignPara->rgpMsgCrl[i]->pbCrlEncoded; } signInfo.cCrlEncoded = pSignPara->cMsgCrl; signInfo.rgCrlEncoded = crlBlob; } else ret = FALSE; } if (pSignPara->dwFlags || pSignPara->dwInnerContentType) FIXME("unimplemented feature\n"); if (ret) msg = CryptMsgOpenToEncode(pSignPara->dwMsgEncodingType, fDetachedSignature ? CMSG_DETACHED_FLAG : 0, CMSG_SIGNED, &signInfo, NULL, NULL); if (msg) { if (cToBeSigned) { for (i = 0; ret && i < cToBeSigned; ++i) { ret = CryptMsgUpdate(msg, rgpbToBeSigned[i], rgcbToBeSigned[i], i == cToBeSigned - 1); } } else ret = CryptMsgUpdate(msg, NULL, 0, TRUE); if (ret) ret = CryptMsgGetParam(msg, CMSG_CONTENT_PARAM, 0, pbSignedBlob, pcbSignedBlob); CryptMsgClose(msg); } else ret = FALSE; CryptMemFree(crlBlob); CryptMemFree(certBlob); if (freeProv) CryptReleaseContext(hCryptProv, 0); return ret; }
void PfxCertificate::init( ByteBuffer pfxBlob, const tstring & password, const tstring & certName) { CRYPT_DATA_BLOB blob = {0}; blob.cbData = static_cast<DWORD>(pfxBlob.getLength()); blob.pbData = (BYTE*) pfxBlob.getPtr(); BOOL recognizedPFX = PFXIsPFXBlob(&blob); DWORD dwErr = GetLastError(); RCF_VERIFY( recognizedPFX, Exception(_RcfError_ApiError("PFXIsPFXBlob()"), dwErr)); std::wstring wPassword = RCF::toWstring(password); // For Windows 98, the flag CRYPT_MACHINE_KEYSET is not valid. mPfxStore = PFXImportCertStore( &blob, wPassword.c_str(), CRYPT_MACHINE_KEYSET | CRYPT_EXPORTABLE); dwErr = GetLastError(); RCF_VERIFY( mPfxStore, Exception(_RcfError_ApiError("PFXImportCertStore()"), dwErr)); PCCERT_CONTEXT pCertStore = NULL; // Tempting to use CERT_FIND_ANY for the case where there is just a single // certificate in the PFX file. However, doing so appears to not load the // private key information. So we use CERT_FIND_SUBJECT_STR instead, and // require the certificate name to be passed in. DWORD dwFindType = CERT_FIND_SUBJECT_STR; std::wstring wCertName = RCF::toWstring(certName); const void * pvFindPara = wCertName.c_str(); pCertStore = CertFindCertificateInStore( mPfxStore, X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, 0, dwFindType, pvFindPara, pCertStore); dwErr = GetLastError(); RCF_VERIFY( pCertStore, Exception(_RcfError_ApiError("CertFindCertificateInStore()"), dwErr)); BOOL bFreeHandle; HCRYPTPROV hProv; DWORD dwKeySpec; BOOL bResult = CryptAcquireCertificatePrivateKey( pCertStore, 0, NULL, &hProv, &dwKeySpec, &bFreeHandle); dwErr = GetLastError(); RCF_VERIFY( bResult, Exception(_RcfError_ApiError("CryptAcquireCertificatePrivateKey()"), dwErr)); mpCert = pCertStore; }
BOOL GetRSAKeyFromCert(PCCERT_CONTEXT pCertContext, BOOL fSign, HCRYPTPROV *hProv, HCRYPTKEY *hPubKey, DWORD *dwKeySpec, BOOL *fFreeProv) { BOOL fResult; BOOL fReturn = FALSE; __try { if (hProv == NULL || hPubKey == NULL || dwKeySpec == NULL || fFreeProv == NULL) { __leave; } *hProv = 0; *hPubKey = 0; *fFreeProv = FALSE; if (fSign) { // Acquire the certificate's private key fResult = CryptAcquireCertificatePrivateKey(pCertContext, CRYPT_ACQUIRE_USE_PROV_INFO_FLAG| CRYPT_ACQUIRE_COMPARE_KEY_FLAG, NULL, hProv, dwKeySpec, fFreeProv); if (!fResult) { MyPrintf(_T("CryptAcquireCertificatePrivateKey failed with %x\n"), GetLastError()); __leave; } } else { fResult = CryptAcquireContext(hProv, NULL, MS_DEF_PROV, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT); if (!fResult) { MyPrintf(_T("CryptAcquireContext failed with %x\n"), GetLastError()); __leave; } *fFreeProv = TRUE; // Import the public key from the certificate so we can verify fResult = CryptImportPublicKeyInfo(*hProv, ENCODING, &(pCertContext->pCertInfo->SubjectPublicKeyInfo), hPubKey); if (!fResult) { MyPrintf(_T("CryptImportPublicKeyInfo failed with %x\n"), GetLastError()); __leave; } } fReturn = TRUE; } __finally { if (!fReturn) { if (*hPubKey != NULL) { CryptDestroyKey(*hPubKey); *hPubKey = NULL; } if ((*fFreeProv == TRUE) && (*hProv != NULL)) { CryptReleaseContext(*hProv, 0); *hProv = NULL; *fFreeProv = FALSE; } } } return fReturn; }
void mod_mimikatz_crypto::listAndOrExportCertificates(vector<wstring> * arguments, bool exportCert) { wstring monEmplacement = L"CERT_SYSTEM_STORE_CURRENT_USER"; wstring monStore = L"My"; if(arguments->size() == 1) { monEmplacement = arguments->front(); } else if(arguments->size() == 2) { monEmplacement = arguments->front(); monStore = arguments->back(); } (*outputStream) << L"Emplacement : \'" << monEmplacement << L'\''; DWORD systemStore; if(mod_crypto::getSystemStoreFromString(monEmplacement, &systemStore)) { (*outputStream) << L"\\" << monStore << endl; if(HCERTSTORE hCertificateStore = CertOpenStore(CERT_STORE_PROV_SYSTEM, NULL, NULL, systemStore | CERT_STORE_OPEN_EXISTING_FLAG | CERT_STORE_READONLY_FLAG, monStore.c_str())) { DWORD i; PCCERT_CONTEXT pCertContext; for (i = 0, pCertContext = CertEnumCertificatesInStore(hCertificateStore, NULL); pCertContext != NULL; pCertContext = CertEnumCertificatesInStore(hCertificateStore, pCertContext), i++) { wstring * certName = new wstring(); bool reussite = false; if(!mod_crypto::getCertNameFromCertCTX(pCertContext, certName)) certName->assign(L"[empty]"); (*outputStream) << L"\t - " << *certName << endl;; sanitizeFileName(certName); wstringstream monBuff; monBuff << monEmplacement << L'_' << monStore << L'_' << i << L'_' << *certName << L'.'; mod_crypto::KIWI_KEY_PROV_INFO keyProvInfo; if(mod_crypto::getKiwiKeyProvInfo(pCertContext, &keyProvInfo)) { (*outputStream) << L"\t\tContainer Clé : " << keyProvInfo.pwszContainerName << endl; (*outputStream) << L"\t\tProvider : " << keyProvInfo.pwszProvName << endl; HCRYPTPROV_OR_NCRYPT_KEY_HANDLE monProv = NULL; DWORD keySpec = 0; BOOL aFermer = false; if(CryptAcquireCertificatePrivateKey(pCertContext, CRYPT_ACQUIRE_ALLOW_NCRYPT_KEY_FLAG /* CRYPT_ACQUIRE_SILENT_FLAG NULL */, NULL, &monProv, &keySpec, &aFermer)) { (*outputStream) << L"\t\tType : " << mod_crypto::KeyTypeToString(keySpec) << endl; DWORD size = 0; bool exportable = false; if(keySpec == CERT_NCRYPT_KEY_SPEC) { if(mod_cryptong::isNcrypt) { reussite = mod_cryptong::getKeySize(&monProv, &size); reussite &=mod_cryptong::isKeyExportable(&monProv, &exportable); if(aFermer) { mod_cryptong::NCryptFreeObject(monProv); } } else (*outputStream) << L"\t\t\tErreur : Clé de type nCrypt, sans nCrypt ?" << endl; } else { DWORD tailleEcrite = 0; DWORD exportability; HCRYPTKEY maCle = NULL; if(reussite = (CryptGetUserKey(monProv, keySpec, &maCle) != 0)) { tailleEcrite = sizeof(DWORD); reussite = (CryptGetKeyParam(maCle, KP_KEYLEN, reinterpret_cast<BYTE *>(&size), &tailleEcrite, NULL) != 0); tailleEcrite = sizeof(DWORD); reussite &= (CryptGetKeyParam(maCle, KP_PERMISSIONS, reinterpret_cast<BYTE *>(&exportability), &tailleEcrite, NULL) != 0); exportable = (exportability & CRYPT_EXPORT) != 0; } if(aFermer) { CryptReleaseContext(monProv, 0); } } if(reussite) { (*outputStream) << L"\t\tExportabilité : " << (exportable ? L"OUI" : L"NON") << endl; (*outputStream) << L"\t\tTaille clé : " << size << endl; } if(exportCert) { wstring PFXFile = monBuff.str(); PFXFile.append(L"pfx"); reussite = mod_crypto::CertCTXtoPFX(pCertContext, PFXFile, L"mimikatz"); (*outputStream) << L"\t\tExport privé dans \'" << PFXFile << L"\' : " << (reussite ? L"OK" : L"KO") << endl; if(!reussite) { (*outputStream) << L"\t\t\t" << mod_system::getWinError() << endl; } } } else (*outputStream) << L"CryptAcquireCertificatePrivateKey : " << mod_system::getWinError() << endl; } if(exportCert) { wstring DERFile = monBuff.str(); DERFile.append(L"der"); reussite = mod_crypto::CertCTXtoDER(pCertContext, DERFile); (*outputStream) << L"\t\tExport public dans \'" << DERFile << L"\' : " << (reussite ? L"OK" : L"KO") << endl; if(!reussite) { (*outputStream) << L"\t\t\t" << mod_system::getWinError() << endl; } } delete certName; } CertCloseStore(hCertificateStore, CERT_CLOSE_STORE_FORCE_FLAG); } else (*outputStream) << L"CertOpenStore : " << mod_system::getWinError() << endl; } else (*outputStream) << L" introuvable !" << endl; }
int _tmain(int argc, _TCHAR* argv[]) { //-------------------------------------------------------------------- // Declare and initialize variables. HCERTSTORE hCertStore = NULL; PCCERT_CONTEXT pCertContext = NULL; TCHAR * pszStoreName = TEXT("MY"); HCRYPTKEY hKey = NULL; HCRYPTPROV hProv = NULL; DWORD dwKeySpec = 0; BOOL bCallerFreeProv = FALSE; HCRYPTHASH hHash; DWORD dwSigLen= 0; BYTE * pbSignature = NULL; //------------------------------------------------------------- // Declare and initialize variables. BYTE *pbBuffer= (BYTE *)"The data that is to be hashed and signed."; DWORD dwBufferLen = strlen((char *)pbBuffer)+1; //-------------------------------------------------------------------- // Open a certificate store. if ( hCertStore = CertOpenSystemStore( NULL, pszStoreName)) { fprintf(stderr,"The store has been opened.\n"); } else { printf("Unable to open store.\n"); goto err; } //-------------------------------------------------------------------- // Display a list of the certificates in the store and // allow the user to select a certificate. if(!(pCertContext = CryptUIDlgSelectCertificateFromStore( hCertStore, // Open the store that contains the certificates to // display NULL, NULL, NULL, CRYPTUI_SELECT_LOCATION_COLUMN, 0, NULL))) { printf("Select Certificate UI failed.\n" ); goto err; } #if 1 //获取CSP句柄 if (!CryptAcquireCertificatePrivateKey(pCertContext, 0, NULL, &hProv, &dwKeySpec, &bCallerFreeProv)) { printf("CryptAcquireCertificatePrivateKey failed.\n" ); goto err; } //获取密钥句柄 if(!CryptGetUserKey(hProv, dwKeySpec, &hKey)) { printf("CryptGetUserKey failed.\n" ); goto err; } //-------------------------------------------------------------------- // Acquire a hash object handle. if(CryptCreateHash( hProv, CALG_MD5, 0, 0, &hHash)) { printf("An empty hash object has been created. \n"); } else { printf("Error during CryptBeginHash!\n"); goto err; } //-------------------------------------------------------------------- // This code assumes that the handle of a cryptographic context // has been acquired and that a hash object has been created // and its handle (hHash) is available. if(CryptHashData( hHash, pbBuffer, dwBufferLen, 0)) { printf("The data buffer has been added to the hash.\n"); } else { printf("Error during CryptHashData.\n"); goto err; } //-------------------------------------------------------------------- // Determine the size of the signature and allocate memory. dwSigLen= 0; if(CryptSignHash( hHash, dwKeySpec, NULL, 0, NULL, &dwSigLen)) { printf("Signature length %d found.\n",dwSigLen); } else { printf("Error during CryptSignHash\n"); goto err; } //-------------------------------------------------------------------- // Allocate memory for the signature buffer. if(pbSignature = (BYTE *)malloc(dwSigLen)) { printf("Memory allocated for the signature.\n"); } else { printf("Out of memory\n"); goto err; } //-------------------------------------------------------------------- // Sign the hash object. if(CryptSignHash( hHash, dwKeySpec, NULL, 0, pbSignature, &dwSigLen)) { printf("pbSignature is the hash signature.\n"); } else { printf("Error during CryptSignHash.\n"); goto err; } { DWORD dwBlobLen = 0; BYTE * pbKeyBlob = 0; HCRYPTKEY hPubKey = 0; if(CryptExportKey( hKey, NULL, PUBLICKEYBLOB, //导出公钥 0, NULL, &dwBlobLen)) //返回密钥数据长度 { printf("Size of the BLOB for the public key determined. \n"); } else { printf("Error computing BLOB length.\n"); goto err; } if(pbKeyBlob = (BYTE*)malloc(dwBlobLen)) { printf("Memory has been allocated for the BLOB. \n"); } else { printf("Out of memory. \n"); goto err; } if(CryptExportKey( hKey, NULL, PUBLICKEYBLOB, 0, pbKeyBlob, //返回密钥数据 &dwBlobLen)) //导出的密钥数据的长度 { printf("Contents have been written to the BLOB. \n"); } else { printf("Error exporting key.\n"); goto err; } if(CryptImportKey(hProv,pbKeyBlob, dwBlobLen, NULL, 0, &hPubKey)) { printf("CryptImportKey OK. \n"); } else { printf("Error CryptImportKey.\n"); goto err; } if(CryptVerifySignature(hHash, pbSignature, dwSigLen,hPubKey,NULL,0)) { printf("verify OK.\n"); } else { printf("Error during CryptVerifySignature.\n"); goto err; } } if(CryptVerifySignature(hHash, pbSignature, dwSigLen,hKey,NULL,0)) { printf("verify OK.\n"); } else { printf("Error during CryptVerifySignature.\n"); goto err; } #endif BYTE* pbMessage = (BYTE*)"CryptoAPI is a good way to handle security"; DWORD cbMessage = strlen((char*) pbMessage)+1; //证书的上下文 CRYPT_SIGN_MESSAGE_PARA SigParams; DWORD cbSignedMessageBlob; BYTE *pbSignedMessageBlob; DWORD cbDecodedMessageBlob; BYTE *pbDecodedMessageBlob; CRYPT_VERIFY_MESSAGE_PARA VerifyParams; const BYTE* MessageArray[] = {pbMessage}; DWORD MessageSizeArray[1]; MessageSizeArray[0] = cbMessage; printf("Begin processing. \n"); printf(" The message to be signed is\n-> %s.\n",pbMessage); //-------------------------------------------------------------------- //初始化签名结构 SigParams.cbSize = sizeof(CRYPT_SIGN_MESSAGE_PARA); SigParams.dwMsgEncodingType = (PKCS_7_ASN_ENCODING | X509_ASN_ENCODING); SigParams.pSigningCert = pCertContext; SigParams.HashAlgorithm.pszObjId = szOID_RSA_MD5; SigParams.HashAlgorithm.Parameters.cbData = NULL; SigParams.cMsgCert = 1; SigParams.rgpMsgCert = &pCertContext; SigParams.cAuthAttr = 0; SigParams.dwInnerContentType = 0; SigParams.cMsgCrl = 0; SigParams.cUnauthAttr = 0; SigParams.dwFlags = 0; SigParams.pvHashAuxInfo = NULL; SigParams.rgAuthAttr = NULL; //首先得到BLOB的大小 if(CryptSignMessage( &SigParams, // Signature parameters FALSE, // Not detached 1, // Number of messages MessageArray, // Messages to be signed MessageSizeArray, // Size of messages NULL, // Buffer for signed message &cbSignedMessageBlob)) // Size of buffer { printf("The size of the BLOB is %d.\n",cbSignedMessageBlob); } else { printf("Getting signed BLOB size failed"); } //-------------------------------------------------------------------- //分配BLOB的内存. if(!(pbSignedMessageBlob = (BYTE*)malloc(cbSignedMessageBlob))) { printf("Memory allocation error while signing."); } if(CryptSignMessage( &SigParams, // FALSE, // 1, //消息数量 MessageArray, //待签名的消息 MessageSizeArray, //消息大小 pbSignedMessageBlob, //缓冲区 &cbSignedMessageBlob)) //缓冲区大小 { printf("The message was signed successfully. \n"); } else { printf("Error getting signed BLOB"); } //-------------------------------------------------------------------- //验证签名信息 //-------------------------------------------------------------------- //初始化VerifyParams结构. VerifyParams.cbSize = sizeof(CRYPT_VERIFY_MESSAGE_PARA); VerifyParams.dwMsgAndCertEncodingType = (PKCS_7_ASN_ENCODING | X509_ASN_ENCODING); VerifyParams.hCryptProv = 0; VerifyParams.pfnGetSignerCertificate = NULL; VerifyParams.pvGetArg = NULL; if(CryptVerifyMessageSignature( &VerifyParams, //. 0, // pbSignedMessageBlob, //. cbSignedMessageBlob, // NULL, // &cbDecodedMessageBlob, // NULL)) // Pointer to signer certificate. { printf("%d bytes need for the buffer.\n",cbDecodedMessageBlob); } else { printf("Verification message failed. \n"); } //为缓冲区分配内存. if(!(pbDecodedMessageBlob = (BYTE*)malloc(cbDecodedMessageBlob))) { printf("Memory allocation error allocating decode BLOB."); } //得到缓冲区的大小 if(CryptVerifyMessageSignature( &VerifyParams, // Verify parameters. 0, // Signer index. pbSignedMessageBlob, // Pointer to signed BLOB. cbSignedMessageBlob, // Size of signed BLOB. pbDecodedMessageBlob, // Buffer for decoded message. &cbDecodedMessageBlob, // Size of buffer. NULL)) // Pointer to signer certificate. { printf("The verified message is \n-> %s \n",pbDecodedMessageBlob); } else { printf("Verification message failed. \n"); } err: WTF_PrintErrorMsg(); if(pbSignedMessageBlob) { free(pbSignedMessageBlob); } if(pbDecodedMessageBlob) { free(pbDecodedMessageBlob); } if (pbSignature) { free(pbSignature); } if(hHash) { CryptDestroyHash(hHash); } if (hKey) { CryptDestroyKey(hKey); } if (hProv) { CryptReleaseContext(hProv, 0); } if (pCertContext) { CertFreeCertificateContext(pCertContext); } if (hCertStore) { CertCloseStore(hCertStore, CERT_CLOSE_STORE_FORCE_FLAG); } return 0; }