Guest User

CertUtil.cpp

a guest
Jul 10th, 2018
201
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 38.81 KB | None | 0 0
  1. //---------------------------------------------------------------------------
  2. // Módulo de certificados digitais
  3. //
  4. #pragma hdrstop
  5.  
  6. #include "CertUtil.h"
  7. #include <string.h>
  8. #include <ctype.h>
  9.  
  10. #pragma comment(lib, "crypt32.lib")
  11. #pragma comment(lib, "cryptxml.lib")
  12. #pragma package(smart_init)
  13.  
  14. //---------------------------------------------------------------------------
  15. // Estrutura para o buffer de dados
  16. //
  17. struct CertUtil_Buffer {
  18.   BYTE *pbData;
  19.   ULONG cbData;
  20.   ULONG cbMaxData;
  21. };
  22.  
  23. //---------------------------------------------------------------------------
  24. // Gravação em buffer de memória
  25. //
  26. static HRESULT CALLBACK CertUtil_writeXmlToBuffer( void *param,
  27.     const BYTE *pbData, ULONG cbData )
  28. {
  29.   HRESULT hr = S_FALSE;
  30.   CertUtil_Buffer *buffer = (CertUtil_Buffer*)param;
  31.  
  32.   if (buffer == NULL)
  33.     hr = E_INVALIDARG;
  34.   else
  35.   {
  36.     if (buffer->pbData == NULL || buffer->cbData + cbData > buffer->cbMaxData)
  37.     {
  38.       ULONG md = buffer->cbMaxData;
  39.       BYTE *pb;
  40.  
  41.       while (md < buffer->cbData + cbData + 256)
  42.         md += 512;
  43.  
  44.       if ((pb = (PBYTE)LocalAlloc( LPTR, (SIZE_T)md )) == NULL)
  45.       {
  46.         hr = HRESULT_FROM_WIN32( GetLastError() );
  47.         if (hr == S_OK)
  48.           hr = E_OUTOFMEMORY;
  49.         return hr;
  50.       }
  51.  
  52.       if (buffer->pbData != NULL)
  53.       {
  54.         memcpy( (void*)pb, (void*)buffer->pbData,
  55.             (size_t)(buffer->cbData * sizeof(BYTE)) );
  56.         LocalFree( buffer->pbData );
  57.       }
  58.       else
  59.         buffer->cbData = 0;
  60.  
  61.       buffer->pbData = pb;
  62.       buffer->cbMaxData = md;
  63.     }
  64.  
  65.     memcpy( (void*)(buffer->pbData + buffer->cbData), (void*)pbData,
  66.         (size_t)(cbData * sizeof(BYTE)) );
  67.     buffer->cbData += cbData;
  68.     hr = S_OK;
  69.   }
  70.  
  71.   return hr;
  72. }
  73.  
  74. //---------------------------------------------------------------------------
  75. // Gravação em arquivo
  76. //
  77. static HRESULT CALLBACK CertUtil_writeXmlToFile( void *param,
  78.     const BYTE *pbData, ULONG cbData )
  79. {
  80.   HRESULT hr = S_FALSE;
  81.   DWORD   bw = 0;
  82.   HANDLE  hFile = (HANDLE)param;
  83.  
  84.   if (INVALID_HANDLE_VALUE == hFile)
  85.     hr = E_INVALIDARG;
  86.   else
  87.   {
  88.     if (!WriteFile( hFile, pbData, cbData, &bw, NULL ))
  89.     {
  90.       hr = HRESULT_FROM_WIN32( GetLastError() );
  91.       if (hr == S_OK)
  92.         hr = E_FAIL;
  93.     }
  94.     else if (bw != cbData)
  95.       hr = E_FAIL;
  96.     else
  97.       hr = S_OK;
  98.   }
  99.  
  100.   return hr;
  101. }
  102.  
  103. //---------------------------------------------------------------------------
  104. // Converte resultado (HRESULT) para o código erro do Windows
  105. //
  106. static DWORD CertUtil_Win32FromHResult( HRESULT hr )
  107. {
  108.   if ((HRESULT)(hr & 0xFFFF0000) == MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, 0))
  109.     return HRESULT_CODE(hr);
  110.  
  111.   if (hr == S_OK)
  112.     return ERROR_SUCCESS;
  113.  
  114.   // Not a Win32 HRESULT so return a generic error code.
  115.   return ERROR_CAN_NOT_COMPLETE;
  116. }
  117.  
  118. //---------------------------------------------------------------------------
  119. // Converte data de arquivo (FILETIME) para TDateTime
  120. //
  121. System::TDateTime CertUtil_FileTimeToDateTime( FILETIME *ft )
  122. {
  123.   SYSTEMTIME stUTC, stLocal;
  124.   System::TDateTime result;
  125.  
  126.   if (FileTimeToSystemTime( ft, &stUTC )
  127.       && SystemTimeToTzSpecificLocalTime( NULL, &stUTC, &stLocal ))
  128.   {
  129.     result = System::TDateTime( (unsigned short)stLocal.wYear,
  130.         (unsigned short)stLocal.wMonth, (unsigned short)stLocal.wDay )
  131.       + System::TDateTime( (unsigned short)stLocal.wHour,
  132.         (unsigned short)stLocal.wMinute, (unsigned short)stLocal.wSecond,
  133.         (unsigned short)stLocal.wMilliseconds );
  134.   }
  135.  
  136.   return result;
  137. }
  138.  
  139. //---------------------------------------------------------------------------
  140. // Contrutor
  141. //
  142. Cert::Cert()
  143. {
  144.   hStore = NULL;
  145.   ctxCert = NULL;
  146.  
  147.   hPrvProv = NULL;
  148.   dwKeySpec = AT_SIGNATURE;
  149.   bFreeProv = FALSE;
  150.  
  151.   ctxChain = NULL;
  152.  
  153.   pfxData.pbData = NULL;
  154.   pfxData.cbData = 0;
  155. }
  156.  
  157. //---------------------------------------------------------------------------
  158. // Destrutor
  159. //
  160. Cert::~Cert()
  161. {
  162.   freeStore( true );
  163. }
  164.  
  165. //---------------------------------------------------------------------------
  166. // Define o último erro / contexto
  167. //
  168. void Cert::error( DWORD err, const System::WideString msg, const System::WideString ctx )
  169. {
  170.   LPVOID lpMsgBuf = NULL;
  171.  
  172.   if (err != 0 && err != ERROR_CAN_NOT_COMPLETE
  173.       && FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER|FORMAT_MESSAGE_FROM_SYSTEM,
  174.         NULL, err, MAKELANGID(LANG_NEUTRAL,SUBLANG_DEFAULT), (LPTSTR)&lpMsgBuf, 0, NULL ) != 0)
  175.     errMsg = (msg.IsEmpty()? System::WideString(): msg + ":\n") + (LPSTR)lpMsgBuf;
  176.   else
  177.     errMsg = msg;
  178.   errCtx = ctx;
  179.  
  180.   if (lpMsgBuf != NULL)
  181.     LocalFree( lpMsgBuf );
  182. }
  183.  
  184. //---------------------------------------------------------------------------
  185. // Abre o repositório de certificados do sistema se nenhum aberto
  186. //
  187. bool Cert::openSystemStore()
  188. {
  189.   if (hStore == NULL && (hStore = CertOpenStore(
  190.           CERT_STORE_PROV_SYSTEM, X509_ASN_ENCODING, NULL,
  191.           CERT_SYSTEM_STORE_CURRENT_USER|CERT_STORE_DEFER_CLOSE_UNTIL_LAST_FREE_FLAG,
  192.           L"My" )) == NULL)
  193.   {
  194.     error( GetLastError(), "Falha abrindo repositório de certificados do sistema",
  195.         __FUNC__ "() : CertOpenStore()" );
  196.     return false;
  197.   }
  198.  
  199.   return (hStore != NULL);
  200. }
  201.  
  202. //---------------------------------------------------------------------------
  203. // Obtém a chave privada e cadeia de certificação do certificado atual
  204. //
  205. bool Cert::openPrivateKey()
  206. {
  207.   if (ctxCert == NULL)
  208.   {
  209.     error( 0, "Falha obtendo chave privada: nenhum certificado aberto",
  210.         __FUNC__ "()" );
  211.     return false;
  212.   }
  213.  
  214.   if (hPrvProv == NULL || ctxChain == NULL)
  215.   {
  216.     CERT_CHAIN_PARA chainPara;
  217.  
  218.     if (hPrvProv == NULL && !CryptAcquireCertificatePrivateKey( ctxCert,
  219.           CRYPT_ACQUIRE_CACHE_FLAG, NULL, &hPrvProv, &dwKeySpec, &bFreeProv ))
  220.     {
  221.       error( GetLastError(), "Falha obtendo chave privada do certificado",
  222.           __FUNC__ "() : CryptAcquireCertificatePrivateKey()" );
  223.       return false;
  224.     }
  225.  
  226.     memset( (void*)&chainPara, '\0', sizeof(CERT_CHAIN_PARA) );
  227.     chainPara.cbSize = sizeof(CERT_CHAIN_PARA);
  228.  
  229.     if (ctxChain == NULL && !CertGetCertificateChain( NULL, ctxCert,
  230.           NULL, NULL, &chainPara, 0, NULL, &ctxChain ))
  231.     {
  232.       error( GetLastError(), "Falha obtendo cadeia de certificação",
  233.           __FUNC__ "() : CertGetCertificateChain()" );
  234.       return false;
  235.     }
  236.   }
  237.  
  238.   return (hPrvProv != NULL && ctxChain != NULL);
  239. }
  240.  
  241. //---------------------------------------------------------------------------
  242. // Libera todos os recursos e fecha o repositório de certificados
  243. //
  244. bool Cert::freeStore( bool closeStore )
  245. {
  246.   bool result = true;
  247.  
  248.   // Contexto do certificado
  249.   if (ctxCert != NULL)
  250.   {
  251.     if (ctxChain != NULL)
  252.     {
  253.       CertFreeCertificateChain( ctxChain );
  254.       ctxChain = NULL;
  255.     }
  256.  
  257.     if (hPrvProv != NULL && bFreeProv && !CryptReleaseContext( hPrvProv, 0 ))
  258.     {
  259.       error( GetLastError(), "Falha fechando provedor criptográfico",
  260.           __FUNC__ "() : CryptReleaseContext()" );
  261.       result = false;
  262.     }
  263.     hPrvProv = NULL;
  264.     dwKeySpec = AT_SIGNATURE;
  265.     bFreeProv = FALSE;
  266.  
  267.     CertFreeCertificateContext( ctxCert );
  268.     ctxCert = NULL;
  269.  
  270.     certFile = System::WideString();
  271.     certName = System::WideString();
  272.     certType = System::WideString();
  273.     name = System::WideString();
  274.     doc = System::WideString();
  275.     loc = System::WideString();
  276.     email = System::WideString();
  277.     validFrom = System::TDateTime();
  278.     validTo = System::TDateTime();
  279.   }
  280.  
  281.   // Repositório de certificados
  282.   if (closeStore && hStore != NULL)
  283.   {
  284.     if (!CertCloseStore( hStore, 0 ))
  285.     {
  286.       error( GetLastError(), "Falha fechando repositório de certificados",
  287.           __FUNC__ "() : CertCloseStore()" );
  288.       result = false;
  289.     }
  290.     hStore = NULL;
  291.  
  292.     if (pfxData.pbData != NULL)
  293.     {
  294.       LocalFree( pfxData.pbData );
  295.       pfxData.pbData = NULL;
  296.       pfxData.cbData = 0;
  297.     }
  298.   }
  299.  
  300.   return result;
  301. }
  302.  
  303. //---------------------------------------------------------------------------
  304. // Retorna e limpa a última mensagem de erro
  305. //
  306. System::WideString Cert::lastError()
  307. {
  308.   System::WideString msg;
  309.  
  310.   msg = errMsg;
  311.  
  312.   if (!errCtx.IsEmpty())
  313.   {
  314.     if (!msg.IsEmpty())
  315.       msg += "\nContexto: " + errCtx;
  316.     else
  317.       msg = "Falha executando " + errCtx;
  318.   }
  319.  
  320.   errMsg = System::WideString();
  321.   errCtx = System::WideString();
  322.  
  323.   return msg;
  324. }
  325.  
  326. //---------------------------------------------------------------------------
  327. // Abre um repositório de certificados em arquivo
  328. //
  329. bool Cert::openFileStore( const System::WideString &fileName, const wchar_t *password )
  330. {
  331.   // Fecha o repositório atualmente aberto
  332.   if (!freeStore( true ))
  333.     return false;
  334.  
  335.   if (pfxData.pbData != NULL)
  336.   {
  337.     LocalFree( pfxData.pbData );
  338.     pfxData.pbData = NULL;
  339.     pfxData.cbData = 0;
  340.   }
  341.  
  342.   // Carrega o arquivo de entrada na memória
  343.   if (!loadFile( fileName, &pfxData.pbData, &pfxData.cbData ))
  344.     return false;
  345.  
  346.   // Verifica o arquivo PFX
  347.   if (!PFXIsPFXBlob( &pfxData ))
  348.   {
  349.     error( 0, "Não é um arquivo PFX válido: " + fileName,
  350.         __FUNC__ "() : PFXIsPFXBlob()" );
  351.     LocalFree( pfxData.pbData );
  352.     pfxData.pbData = NULL;
  353.     pfxData.cbData = 0;
  354.     return false;
  355.   }
  356.  
  357.   if (!PFXVerifyPassword( &pfxData, password, 0 ))
  358.   {
  359.     error( 0, "Senha inválida para o arquivo PFX",
  360.         __FUNC__ "() : PFXVerifyPassword()" );
  361.     LocalFree( pfxData.pbData );
  362.     pfxData.pbData = NULL;
  363.     pfxData.cbData = 0;
  364.     return false;
  365.   }
  366.  
  367.   // Abre o arquivo PFX
  368.   if ((hStore = PFXImportCertStore( &pfxData, password, 0 )) == NULL
  369.       && password[0] != L'\0' && (hStore = PFXImportCertStore( &pfxData, NULL, 0 )) == NULL)
  370.   {
  371.     error( GetLastError(), "Falha abrindo arquivo de certificados",
  372.         __FUNC__ "() : PFXImportCertStore()" );
  373.     LocalFree( pfxData.pbData );
  374.     pfxData.pbData = NULL;
  375.     pfxData.cbData = 0;
  376.     return false;
  377.   }
  378.  
  379.   certFile = fileName;
  380.  
  381.   return true;
  382. }
  383.  
  384. //---------------------------------------------------------------------------
  385. // Lista os certificados no repositório aberto ou do sistema
  386. //
  387. bool Cert::listCert( Classes::TStrings &lst )
  388. {
  389.   int n = 0;
  390.   PCCERT_CONTEXT ctx = NULL;
  391.   wchar_t szName[MAX_PATH];
  392.   szName[MAX_PATH-1] = '\0';
  393.  
  394.   if (!openSystemStore())
  395.     return false;
  396.  
  397.   lst.Clear();
  398.  
  399.   while ((ctx = CertEnumCertificatesInStore( hStore, ctx )) != NULL)
  400.   {
  401.     ++n;
  402.     if (n > 99)
  403.     {
  404.       lst.Add( "..." );
  405.       break;
  406.     }
  407.  
  408.     if (CertGetNameString( ctx, CERT_NAME_SIMPLE_DISPLAY_TYPE,
  409.           0, NULL, szName, MAX_PATH-1 ))
  410.       lst.Add( System::WideString( szName ) );
  411.     else
  412.     {
  413.       error( 0, "Falha obtendo nome do certificado",
  414.           __FUNC__ "() : CertGetNameString()" );
  415.       CertFreeCertificateContext( ctx );
  416.       return false;
  417.     }
  418.   }
  419.  
  420.   if (ctx != NULL)
  421.     CertFreeCertificateContext( ctx );
  422.  
  423.   return true;
  424. }
  425.  
  426. //---------------------------------------------------------------------------
  427. // Abre um certificado no repositório aberto ou do sistema
  428. //
  429. bool Cert::openCert( const System::WideString &cert )
  430. {
  431.   int n = 0;
  432.   PCCERT_CONTEXT ctx = NULL;
  433.   wchar_t szName[MAX_PATH], *ptr, *ep;
  434.   szName[MAX_PATH-1] = '\0';
  435.  
  436.   // Fecha o contexto atualmente aberto
  437.   if (!freeStore( false ))
  438.     return false;
  439.  
  440.   // Abre o repositório de certificados do sistema se nenhum aberto
  441.   if (!openSystemStore())
  442.     return false;
  443.  
  444.   // Localiza um certificado que seja válido na data atual
  445.   while ((ctx = CertFindCertificateInStore(
  446.           hStore, X509_ASN_ENCODING, 0, (cert.IsEmpty()? CERT_FIND_ANY: CERT_FIND_SUBJECT_STR),
  447.           (cert.IsEmpty()? NULL: cert.c_bstr()), ctx )) != NULL)
  448.   {
  449.     ++n;
  450.     if (n > 99)
  451.       break;
  452.  
  453.     validFrom = CertUtil_FileTimeToDateTime( &ctx->pCertInfo->NotBefore );
  454.     validTo = CertUtil_FileTimeToDateTime( &ctx->pCertInfo->NotAfter );
  455.  
  456.     if (validFrom < TDateTime::CurrentDateTime() && validTo > TDateTime::CurrentDateTime())
  457.       break;
  458.   }
  459.  
  460.   // Nenhum certificado encontrado
  461.   if (n == 0)
  462.   {
  463.     error( GetLastError(), "Falha localizando certificado",
  464.         __FUNC__ "() : CertFindCertificateInStore()" );
  465.     return false;
  466.   }
  467.  
  468.   // Se nenhum certificado é válido na data atual, pega o primeiro
  469.   if (ctx == NULL)
  470.   {
  471.     if ((ctxCert = CertFindCertificateInStore(
  472.             hStore, X509_ASN_ENCODING, 0, (cert.IsEmpty()? CERT_FIND_ANY: CERT_FIND_SUBJECT_STR),
  473.             (cert.IsEmpty()? NULL: cert.c_bstr()), NULL )) == NULL)
  474.     {
  475.       error( GetLastError(), "Falha localizando certificado",
  476.           __FUNC__ "() : CertFindCertificateInStore()" );
  477.       return false;
  478.     }
  479.  
  480.     validFrom = CertUtil_FileTimeToDateTime( &ctxCert->pCertInfo->NotBefore );
  481.     validTo = CertUtil_FileTimeToDateTime( &ctxCert->pCertInfo->NotAfter );
  482.   }
  483.   else
  484.     ctxCert = ctx;
  485.  
  486.   // Dados restantes do certificado
  487.   if (CertGetNameString( ctxCert, CERT_NAME_SIMPLE_DISPLAY_TYPE,
  488.         0, NULL, szName, MAX_PATH-1 ))
  489.     certName = System::WideString( szName );
  490.   else
  491.   {
  492.     error( 0, "Falha obtendo nome do requerente do certificado",
  493.         __FUNC__ "() : CertGetNameString()" );
  494.     return false;
  495.   }
  496.  
  497.   if (CertGetNameString( ctxCert, CERT_NAME_EMAIL_TYPE,
  498.         0, NULL, szName, MAX_PATH-1 ))
  499.     email = System::WideString( szName );
  500.   else
  501.     email = System::WideString();
  502.  
  503.   // Dados do emissor do certificado
  504.   if (CertGetNameString( ctxCert, CERT_NAME_SIMPLE_DISPLAY_TYPE,
  505.         CERT_NAME_ISSUER_FLAG, NULL, szName, MAX_PATH-1 ))
  506.     issuerName = System::WideString( szName );
  507.   else
  508.   {
  509.     error( 0, "Falha obtendo nome do emissor do certificado",
  510.         __FUNC__ "() : CertGetNameString()" );
  511.     return false;
  512.   }
  513.  
  514.   // Distinguished Name
  515.   if (CertNameToStr( X509_ASN_ENCODING, &ctxCert->pCertInfo->Subject,
  516.         CERT_X500_NAME_STR, szName, MAX_PATH-1 ) == 0)
  517.   {
  518.     error( 0, "Falha obtendo Distinguished Name do certificado",
  519.         __FUNC__ "() : CertNameToStr()" );
  520.     return false;
  521.   }
  522.  
  523.   //C=BR,
  524.   //S=<UF>,
  525.   //L=<CIDADE>,
  526.   //O=ICP-Brasil,
  527.   //OU=Secretaria da Receita Federal do Brasil - RFB,
  528.   //OU=<RFB e-*** **>,
  529.   //[OU=<Domínio do certificado>]
  530.   //OU=<Identificação da AR>,
  531.   //CN=<Nome Empresarial><:><número de inscrição no CPF/CNPJ>
  532.  
  533.   // Tipo de certificado
  534.   if ((ptr = wcsstr( szName, L"OU=" )) != NULL
  535.       && (ptr = wcsstr( ptr+3, L"OU=" )) != NULL)
  536.   {
  537.     ptr += 3;
  538.     if ((ep = wcsstr( ptr, L", " )) != NULL)
  539.       *ep = L'\0';
  540.     certType = System::WideString( ptr );
  541.     if (ep != NULL)
  542.       *ep = L',';
  543.   }
  544.   else
  545.     certType = System::WideString();
  546.  
  547.   // Nome Empresarial/Pessoa Física e número de inscrição no CPF/CNPJ
  548.   if ((ptr = wcsstr( szName, L"CN=" )) != NULL
  549.       && (ep = wcschr( ptr, L':' )) != NULL)
  550.   {
  551.     ptr += 3;
  552.     *ep = L'\0';
  553.     name = System::WideString( ptr );
  554.     *ep = L':';
  555.     ptr = ep + 1;
  556.     if ((ep = wcsstr( ptr, L", " )) != NULL)
  557.       *ep = L'\0';
  558.     doc = System::WideString( ptr );
  559.     if (ep != NULL)
  560.       *ep = L',';
  561.   }
  562.   else
  563.   {
  564.     name = System::WideString();
  565.     doc = System::WideString();
  566.   }
  567.  
  568.   // Localização
  569.   if ((ptr = wcsstr( szName, L"L=" )) != NULL)
  570.   {
  571.     ptr += 2;
  572.     if ((ep = wcsstr( ptr, L", " )) != NULL)
  573.       *ep = L'\0';
  574.     loc = System::WideString( ptr );
  575.     if (ep != NULL)
  576.       *ep = L',';
  577.     if ((ptr = wcsstr( szName, L"S=" )) != NULL
  578.         || (ptr = wcsstr( szName, L"ST=" )) != NULL)
  579.     {
  580.       if (ptr[1] == L'=')
  581.         ptr += 2;
  582.       else
  583.         ptr += 3;
  584.       if ((ep = wcsstr( ptr, L", " )) != NULL)
  585.         *ep = L'\0';
  586.       loc += System::WideString( L"-" );
  587.       loc += System::WideString( ptr );
  588.       if (ep != NULL)
  589.         *ep = L',';
  590.     }
  591.   }
  592.   else
  593.     loc = System::WideString();
  594.  
  595.   return true;
  596. }
  597.  
  598. //---------------------------------------------------------------------------
  599. // Carrega o arquivo na memória
  600. //
  601. bool Cert::loadFile( const System::WideString &fileName,
  602.     BYTE **ppbData, DWORD *pcbData )
  603. {
  604.   HANDLE  hFile;
  605.   DWORD   br = 0;
  606.  
  607.   *ppbData = NULL;
  608.   *pcbData = 0;
  609.  
  610.   if ((hFile = CreateFile( fileName.c_bstr(), GENERIC_READ, 0, NULL,
  611.           OPEN_EXISTING, 0, NULL )) == INVALID_HANDLE_VALUE)
  612.   {
  613.     error( GetLastError(), "Falha abrindo o arquivo " + fileName,
  614.         __FUNC__ "() : CreateFile()" );
  615.     return false;
  616.   }
  617.  
  618.   if ((*pcbData = GetFileSize( hFile, NULL )) == INVALID_FILE_SIZE)
  619.   {
  620.     error( GetLastError(), "Falha obtendo tamanho do arquivo " + fileName,
  621.         __FUNC__ "() : GetFileSize()" );
  622.     CloseHandle( hFile );
  623.     return false;
  624.   }
  625.   else if (*pcbData == 0)
  626.   {
  627.     error( 0, "Arquivo de entrada vazio: " + fileName,
  628.         __FUNC__ "()" );
  629.     CloseHandle( hFile );
  630.     return false;
  631.   }
  632.  
  633.   if ((*ppbData = (PBYTE)LocalAlloc( LPTR, (SIZE_T)*pcbData )) == NULL)
  634.   {
  635.     DWORD err = GetLastError();
  636.     error( (err == 0? ERROR_OUTOFMEMORY: err), "", __FUNC__ "() : LocalAlloc()" );
  637.     CloseHandle( hFile );
  638.     return false;
  639.   }
  640.  
  641.   if (!ReadFile( hFile, *ppbData, *pcbData, &br, NULL ))
  642.   {
  643.     error( GetLastError(), "Falha lendo o arquivo " + fileName,
  644.         __FUNC__ "() : ReadFile()" );
  645.     CloseHandle( hFile );
  646.     LocalFree( *ppbData );
  647.     *ppbData = NULL;
  648.     return false;
  649.   }
  650.   else if (br != *pcbData)
  651.   {
  652.     error( 0, "Falha lendo o arquivo " + fileName
  653.         + ":\nO tamanho do arquivo difere dos bytes lidos",
  654.         __FUNC__ "() : ReadFile()" );
  655.     CloseHandle( hFile );
  656.     LocalFree( *ppbData );
  657.     *ppbData = NULL;
  658.     return false;
  659.   }
  660.  
  661.   CloseHandle( hFile );
  662.  
  663.   return true;
  664. }
  665.  
  666. //---------------------------------------------------------------------------
  667. // Salva o conteúdo da memória em um arquivo
  668. //
  669. bool Cert::writeFile( const System::WideString &fileOut,
  670.     BYTE *pbData, DWORD cbData )
  671. {
  672.   HANDLE hFile;
  673.   DWORD bw = 0;
  674.  
  675.   // Cria o arquivo de saída
  676.   if ((hFile = CreateFile( fileOut.c_bstr(), GENERIC_WRITE, 0, NULL,
  677.           CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL )) == INVALID_HANDLE_VALUE)
  678.   {
  679.     error( GetLastError(), "Falha criando o arquivo " + fileOut,
  680.         __FUNC__ "() : CreateFile()" );
  681.     return false;
  682.   }
  683.  
  684.   // Grava o arquivo de saída
  685.   if (!WriteFile( hFile, pbData, cbData, &bw, NULL ) || bw != cbData)
  686.   {
  687.     error( GetLastError(), "Falha gravando o arquivo " + fileOut,
  688.         __FUNC__ "() : WriteFile()" );
  689.     CloseHandle( hFile );
  690.     return false;
  691.   }
  692.  
  693.   CloseHandle( hFile );
  694.  
  695.   return true;
  696. }
  697.  
  698. //---------------------------------------------------------------------------
  699. // Localiza e monta o caminho XPath de uma TAG e extrai sua propriedade Id
  700. //
  701. bool Cert::loadTagXPathId( const BYTE *pbData, const DWORD cbData,
  702.     const System::WideString &tag, System::WideString &tag_xpath,
  703.     System::WideString &tag_id )
  704. {
  705.   System::WideString xpath[CERTUTIL_LEVEL_MAX];
  706.   char t[CERTUTIL_TAG_SIZE];
  707.   int i, j, level;
  708.  
  709.   level = 0;
  710.   for (i = 0; i < (int)cbData; ++i)
  711.   {
  712.     // Início de uma marcação
  713.     if (pbData[i] == '<')
  714.     {
  715.       // TAG inicial
  716.       if (isalpha( pbData[++i] ) || pbData[i] == '_')
  717.       {
  718.         // Obtém o nome da TAG, incluindo o 'namespace'
  719.         for (j = 0; i < (int)cbData && j < CERTUTIL_TAG_SIZE-1
  720.             && (isalnum( pbData[i] ) || pbData[i] == '_' || pbData[i] == '-'
  721.               || pbData[i] == '.' || pbData[i] == ':'); ++i, ++j)
  722.           t[j] = pbData[i];
  723.         t[j] = '\0';
  724.  
  725.         // Salva o caminho da TAG
  726.         if (level < CERTUTIL_LEVEL_MAX)
  727.           xpath[level++] = t;
  728.  
  729.         // Se for a TAG selecionada
  730.         if (tag == t)
  731.         {
  732.           tag_xpath = "";
  733.           for (j = 0; j < level; ++j)
  734.             tag_xpath += "/" + xpath[j];
  735.  
  736.           while (i < (int)cbData && pbData[i] != '>')
  737.           {
  738.             // Atributo da TAG
  739.             if (isalpha( pbData[i] ) || pbData[i] == '_')
  740.             {
  741.               // Identificação da TAG
  742.               if (strnicmp( &pbData[i], "Id=\"", 4 ) == 0)
  743.               {
  744.                 i += 4;
  745.                 for (j = 0; i < (int)cbData && j < CERTUTIL_TAG_SIZE-1
  746.                     && pbData[i] != '\"' && pbData[i] != '>'; ++i, ++j)
  747.                   t[j] = pbData[i];
  748.                 t[j] = '\0';
  749.  
  750.                 tag_id = System::WideString("#") + t;
  751.  
  752.                 return true;
  753.               }
  754.               // Outros atributos
  755.               else
  756.               {
  757.                 while (i < (int)cbData && (isalnum( pbData[i] ) || pbData[i] == '_'
  758.                       || pbData[i] == '-' || pbData[i] == '.' || pbData[i] == ':'))
  759.                   ++i;
  760.               }
  761.             }
  762.             // Cadeia de caracteres
  763.             else if (pbData[i] == '\"')
  764.             {
  765.               do
  766.                 ++i;
  767.               while (i < (int)cbData && pbData[i] != '\"' && pbData[i] != '>');
  768.               if (pbData[i] != '>')
  769.                 ++i;
  770.             }
  771.             else
  772.               ++i;
  773.           }
  774.  
  775.           // TAG sem Id
  776.           tag_id = "";
  777.  
  778.           return true;
  779.         }
  780.         // Outras TAGs
  781.         else
  782.         {
  783.           while (i < (int)cbData && pbData[i] != '>')
  784.             ++i;
  785.         }
  786.       }
  787.       // TAG final
  788.       else if (pbData[i] == '/')
  789.       {
  790.         if (isalpha( pbData[++i] ) || pbData[i] == '_')
  791.         {
  792.           for (j = 0; i < (int)cbData && j < CERTUTIL_TAG_SIZE-1
  793.               && (isalnum( pbData[i] ) || pbData[i] == '_' || pbData[i] == '-'
  794.                 || pbData[i] == '.' || pbData[i] == ':'); ++i, ++j)
  795.             t[j] = pbData[i];
  796.           t[j] = '\0';
  797.  
  798.           for (j = level-1; j >= 0 && xpath[j] != t; --j)
  799.             ;
  800.           if (j >= 0)
  801.             level = j;
  802.         }
  803.         while (i < (int)cbData && pbData[i] != '>')
  804.           ++i;
  805.       }
  806.       // Outros tipos de marcação
  807.       else
  808.       {
  809.         while (i < (int)cbData && pbData[i] != '>')
  810.           ++i;
  811.       }
  812.     }
  813.   }
  814.  
  815.   return false;
  816. }
  817.  
  818. //---------------------------------------------------------------------------
  819. // Assina um arquivo XML (de um arquivo para outro)
  820. //
  821. bool Cert::signXMLFile( const System::WideString &fileOut,
  822.     const System::WideString &fileIn, const System::WideString &tag )
  823. {
  824.   BYTE *pbData;
  825.   DWORD cbData;
  826.  
  827.   // Carrega o arquivo de entrada na memória
  828.   if (!loadFile( fileIn, &pbData, &cbData ))
  829.     return false;
  830.  
  831.   // Assina o conteúdo do arquivo
  832.   if (!signXMLBuffer( &pbData, &cbData, tag, true ))
  833.   {
  834.     LocalFree( pbData );
  835.     return false;
  836.   }
  837.  
  838.   // Grava o arquivo de saída
  839.   if (!writeFile( fileOut, pbData, cbData ))
  840.   {
  841.     LocalFree( pbData );
  842.     return false;
  843.   }
  844.  
  845.   LocalFree( pbData );
  846.  
  847.   return true;
  848. }
  849.  
  850. //---------------------------------------------------------------------------
  851. // Assina um arquivo XML (da memória para um arquivo)
  852. //
  853. bool Cert::signXMLBufferToFile( const System::WideString &fileOut,
  854.     BYTE *pbData, DWORD cbData, const System::WideString &tag )
  855. {
  856.   // Assina o conteúdo da memória
  857.   if (!signXMLBuffer( &pbData, &cbData, tag, false ))
  858.     return false;
  859.  
  860.   // Grava o arquivo de saída
  861.   if (!writeFile( fileOut, pbData, cbData ))
  862.   {
  863.     LocalFree( pbData );
  864.     return false;
  865.   }
  866.  
  867.   LocalFree( pbData );
  868.  
  869.   return true;
  870. }
  871.  
  872. //---------------------------------------------------------------------------
  873. // Assina um arquivo XML (num buffer de memória)
  874. //
  875. bool Cert::signXMLBuffer( BYTE **pbData, DWORD *cbData,
  876.     const System::WideString &tag, bool freeData )
  877. {
  878.   HRESULT hr;
  879.   HCRYPTXML hSig = NULL;
  880.   HCRYPTXML hRef = NULL;
  881.  
  882.   CRYPT_XML_ALGORITHM xmlAlg_CanonicalizationMethod = {
  883.     sizeof(CRYPT_XML_ALGORITHM),
  884.     wszURI_CANONICALIZATION_C14N,
  885.     CRYPT_XML_CHARSET_AUTO,
  886.     0,
  887.     NULL
  888.   };
  889.  
  890.   CRYPT_XML_ALGORITHM xmlAlg_DigestMethod = {
  891.     sizeof( CRYPT_XML_ALGORITHM ),
  892.     wszURI_XMLNS_DIGSIG_SHA1,
  893.     CRYPT_XML_CHARSET_AUTO,
  894.     0,
  895.     NULL
  896.   };
  897.  
  898.   CRYPT_XML_ALGORITHM xmlAlg_SignatureMethod = {
  899.     sizeof( CRYPT_XML_ALGORITHM ),
  900.     wszURI_XMLNS_DIGSIG_RSA_SHA1,
  901.     CRYPT_XML_CHARSET_AUTO,
  902.     0,
  903.     NULL
  904.   };
  905.  
  906.   ULONG trans_cnt = 2;
  907.   CRYPT_XML_ALGORITHM trans[] = {
  908.     {
  909.       sizeof( CRYPT_XML_ALGORITHM ),
  910.       wszURI_XMLNS_TRANSFORM_ENVELOPED,
  911.       CRYPT_XML_CHARSET_AUTO,
  912.       0,
  913.       NULL
  914.     },
  915.     {
  916.       sizeof(CRYPT_XML_ALGORITHM),
  917.       wszURI_CANONICALIZATION_C14N,
  918.       CRYPT_XML_CHARSET_AUTO,
  919.       0,
  920.       NULL
  921.     }
  922.   };
  923.  
  924.   CRYPT_XML_BLOB encoded = { CRYPT_XML_CHARSET_AUTO, 0, NULL };
  925.  
  926.   ULONG loc_prop_cnt = 0;
  927.   //DWORD out_len = 76;
  928.   CRYPT_XML_PROPERTY loc_prop[] = {
  929.     {
  930.       CRYPT_XML_PROPERTY_SIGNATURE_LOCATION,
  931.       NULL,
  932.       sizeof(LPCWSTR)
  933.     }/*,
  934.     {
  935.       CRYPT_XML_PROPERTY_HMAC_OUTPUT_LENGTH,
  936.       NULL,
  937.       sizeof(DWORD)
  938.     }*/
  939.   };
  940.  
  941.   BOOL enc_decl = TRUE;
  942.   ULONG enc_prop_cnt = 0;
  943.   CRYPT_XML_PROPERTY enc_prop[] = {
  944.     {
  945.       CRYPT_XML_PROPERTY_DOC_DECLARATION,
  946.       NULL,
  947.       sizeof(BOOL)
  948.     }
  949.   };
  950.  
  951.   ULONG chain_cnt;
  952.   //CERT_BLOB chain[CERTUTIL_CHAIN_MAX];
  953.   CERT_BLOB chain[1];
  954.   CRYPT_XML_KEYINFO_PARAM keyInfo;
  955.  
  956.   CertUtil_Buffer buffer;
  957.  
  958.   System::WideString tag_xpath, tag_id;
  959.   LPCWSTR wszLoc, wszUri;
  960.   wchar_t tag_loc[CERTUTIL_TAG_SIZE];
  961.   wchar_t tag_ref[CERTUTIL_TAG_SIZE];
  962.  
  963.   enc_prop[0].pvValue = &enc_decl;
  964.   enc_prop_cnt = 1;
  965.  
  966.   // Obtém a chave privada do certificado atualmente aberto
  967.   if (!openPrivateKey())
  968.     return false;
  969.  
  970.   // Localiza e monta o caminho da TAG e extrai a propriedade Id
  971.   if (!loadTagXPathId( *pbData, *cbData, tag, tag_xpath, tag_id ))
  972.   {
  973.     error( 0, "Não foi localizada a TAG " + tag,
  974.         __FUNC__ "() : loadTagXPathId()" );
  975.     return false;
  976.   }
  977.   else if (tag_id.IsEmpty())
  978.   {
  979.     error( 0, "Não foi localizada o atributo Id da TAG " + tag,
  980.         __FUNC__ "() : loadTagXPathId()" );
  981.     return false;
  982.   }
  983.   wcscpy( tag_loc, tag_xpath.c_bstr() );
  984.   wcscpy( tag_ref, tag_id.c_bstr() );
  985.   wszLoc = tag_loc;
  986.   wszUri = tag_ref;
  987.   loc_prop[0].pvValue = &wszLoc;
  988.   //loc_prop[1].pvValue = &out_len;
  989.   loc_prop_cnt = 1;
  990.  
  991.   // Inicializa a assinatura do arquivo XML
  992.   encoded.pbData = *pbData;
  993.   encoded.cbData = *cbData;
  994.  
  995.   if ((hr = CryptXmlOpenToEncode( NULL, 0, L"", loc_prop, loc_prop_cnt, &encoded, &hSig )) != S_OK)
  996.   {
  997.     error( CertUtil_Win32FromHResult(hr), "Falha criando assinatura XML",
  998.         __FUNC__ "() : CryptXmlOpenToEncode()" );
  999.     return false;
  1000.   }
  1001.  
  1002.   // Cria a referência
  1003.   if ((hr = CryptXmlCreateReference( hSig, 0, NULL, wszUri, NULL,
  1004.           &xmlAlg_DigestMethod, trans_cnt, trans, &hRef )) != S_OK)
  1005.   {
  1006.     error( CertUtil_Win32FromHResult(hr), "Falha criando referência da assinatura XML",
  1007.         __FUNC__ "() : CryptXmlCreateReference()" );
  1008.     CryptXmlClose( hSig );
  1009.     return false;
  1010.   }
  1011.  
  1012.   // Monta a cadeia de certificados
  1013.   //memset( (void*)chain, '\0', sizeof(CERT_BLOB)*CERTUTIL_CHAIN_MAX );
  1014.   memset( (void*)chain, '\0', sizeof(CERT_BLOB) );
  1015.   memset( (void*)&keyInfo, '\0', sizeof(CRYPT_XML_KEYINFO_PARAM) );
  1016.   chain[0].pbData = ctxChain->rgpChain[0]->rgpElement[0]->pCertContext->pbCertEncoded;
  1017.   chain[0].cbData = ctxChain->rgpChain[0]->rgpElement[0]->pCertContext->cbCertEncoded;
  1018.   chain_cnt = 1;
  1019.   keyInfo.cCertificate = chain_cnt;
  1020.   keyInfo.rgCertificate = chain;
  1021.  
  1022.   // Gera a assinatura digital
  1023.   if ((hr = CryptXmlSign( hSig, hPrvProv, dwKeySpec, 0,
  1024.           CRYPT_XML_KEYINFO_SPEC_PARAM, &keyInfo,
  1025.           &xmlAlg_SignatureMethod, &xmlAlg_CanonicalizationMethod )) != S_OK)
  1026.   {
  1027.     error( CertUtil_Win32FromHResult(hr), "Falha gerando assinatura XML",
  1028.         __FUNC__ "() : CryptXmlSign()" );
  1029.     CryptXmlClose( hSig );
  1030.     return false;
  1031.   }
  1032.  
  1033.   // Cria o buffer de dados
  1034.   if ((buffer.pbData = (PBYTE)LocalAlloc( LPTR, (SIZE_T)(*cbData+CERTUTIL_SIGN_SIZE) )) == NULL)
  1035.   {
  1036.     DWORD err = GetLastError();
  1037.     error( (err == 0? ERROR_OUTOFMEMORY: err), "", __FUNC__ "() : LocalAlloc()" );
  1038.     CryptXmlClose( hSig );
  1039.     return false;
  1040.   }
  1041.   buffer.cbData = 0;
  1042.   buffer.cbMaxData = (ULONG)(*cbData+CERTUTIL_SIGN_SIZE);
  1043.  
  1044.   // Grava o arquivo XML com a assinatura no buffer de dados
  1045.   if ((hr = CryptXmlEncode( hSig, CRYPT_XML_CHARSET_UTF8,
  1046.           enc_prop, enc_prop_cnt, (void*)&buffer, CertUtil_writeXmlToBuffer )) != S_OK)
  1047.   {
  1048.     error( CertUtil_Win32FromHResult(hr), "Falha codificando arquivo XML assinado",
  1049.         __FUNC__ "() : CryptXmlEncode()" );
  1050.     LocalFree( buffer.pbData );
  1051.     CryptXmlClose( hSig );
  1052.     return false;
  1053.   }
  1054.   CryptXmlClose( hSig );
  1055.  
  1056.   // Corrige os dados do buffer
  1057.   // a biblioteca CryptXML coloca o elemento <Signature>
  1058.   // antes da tag de fechamento </infNFe> e não depois
  1059.   if (strncmp( buffer.pbData, "<?xml", 5 ) == 0)
  1060.   {
  1061.     const char *signt = "<Signature";
  1062.     char endt[CERTUTIL_TAG_SIZE];
  1063.     char *p, *q;
  1064.     int n;
  1065.  
  1066.     strcpy( endt, System::AnsiString("</"+tag+">").c_str() );
  1067.     n = strlen( endt );
  1068.     p = strstr( (char*)buffer.pbData, endt );
  1069.     q = strstr( (char*)buffer.pbData, signt );
  1070.     if (p != NULL && q != NULL && p > q)
  1071.     {
  1072.       memmove( q + n, q, p-q );
  1073.       memcpy( q, endt, n );
  1074.     }
  1075.   }
  1076.  
  1077.   // Libera a memória originalmente apontada por *pbData, se necessário
  1078.   if (freeData)
  1079.     LocalFree( *pbData );
  1080.  
  1081.   // Retorna o conteúdo assinado
  1082.   *pbData = buffer.pbData;
  1083.   *cbData = buffer.cbData;
  1084.  
  1085.   return true;
  1086. }
  1087.  
  1088. //---------------------------------------------------------------------------
  1089. // Verifica se um arquivo XML tem assinatura
  1090. //
  1091. bool Cert::signedXMLFile( const System::WideString &fileName )
  1092. {
  1093.   BYTE *pbData;
  1094.   DWORD cbData;
  1095.  
  1096.   // Carrega o arquivo na memória
  1097.   if (!loadFile( fileName, &pbData, &cbData ))
  1098.     return false;
  1099.  
  1100.   // Verifica a(s) assinatura(s) do arquivo XML
  1101.   if (!signedXMLBuffer( pbData, cbData ))
  1102.   {
  1103.     LocalFree( pbData );
  1104.     return false;
  1105.   }
  1106.  
  1107.   LocalFree( pbData );
  1108.  
  1109.   return true;
  1110. }
  1111.  
  1112. //---------------------------------------------------------------------------
  1113. // Verifica a assinatura de um arquivo XML
  1114. //
  1115. bool Cert::verifyXMLFile( const System::WideString &fileName )
  1116. {
  1117.   BYTE *pbData;
  1118.   DWORD cbData;
  1119.  
  1120.   // Carrega o arquivo na memória
  1121.   if (!loadFile( fileName, &pbData, &cbData ))
  1122.     return false;
  1123.  
  1124.   // Verifica a(s) assinatura(s) do arquivo XML
  1125.   if (!verifyXMLBuffer( pbData, cbData ))
  1126.   {
  1127.     LocalFree( pbData );
  1128.     return false;
  1129.   }
  1130.  
  1131.   LocalFree( pbData );
  1132.  
  1133.   return true;
  1134. }
  1135.  
  1136. //---------------------------------------------------------------------------
  1137. // Verifica se uma cadeia XML tem assinatura
  1138. //
  1139. bool Cert::signedXMLBuffer( BYTE *pbData, DWORD cbData )
  1140. {
  1141.   HRESULT hr;
  1142.  
  1143.   HCRYPTXML hDoc = NULL;
  1144.   const CRYPT_XML_DOC_CTXT *pDoc = NULL;
  1145.  
  1146.   CRYPT_XML_BLOB encoded = { CRYPT_XML_CHARSET_AUTO, 0, NULL };
  1147.  
  1148.   encoded.pbData = pbData;
  1149.   encoded.cbData = cbData;
  1150.  
  1151.   // Carrega a(s) assinatura(s) da cadeia XML
  1152.   if ((hr = CryptXmlOpenToDecode( NULL, 0, NULL, 0, &encoded, &hDoc )) != S_OK)
  1153.   {
  1154.     error( CertUtil_Win32FromHResult(hr), "Falha verificando arquivo XML",
  1155.         __FUNC__ "() : CryptXmlOpenToDecode()" );
  1156.     return false;
  1157.   }
  1158.  
  1159.   if ((hr = CryptXmlGetDocContext( hDoc, &pDoc )) != S_OK)
  1160.   {
  1161.     error( CertUtil_Win32FromHResult(hr), "Falha verificando arquivo XML",
  1162.         __FUNC__ "() : CryptXmlGetDocContext()" );
  1163.     CryptXmlClose( hDoc );
  1164.     return false;
  1165.   }
  1166.  
  1167.   if (pDoc->cSignature > 0)
  1168.     hr = S_OK;
  1169.   else
  1170.     hr = S_FALSE;
  1171.  
  1172.   CryptXmlClose( hDoc );
  1173.  
  1174.   return (hr == S_OK);
  1175. }
  1176.  
  1177. //---------------------------------------------------------------------------
  1178. // Verifica a assinatura de uma cadeia XML
  1179. //
  1180. bool Cert::verifyXMLBuffer( BYTE *pbData, DWORD cbData )
  1181. {
  1182.   HRESULT hr;
  1183.  
  1184.   HCRYPTXML hDoc = NULL;
  1185.   const CRYPT_XML_DOC_CTXT *pDoc = NULL;
  1186.   const CRYPT_XML_SIGNATURE *pSig = NULL;
  1187.   const CRYPT_XML_REFERENCE *pRef = NULL;
  1188.  
  1189.   BCRYPT_KEY_HANDLE hKey = NULL;
  1190.   PCCERT_CONTEXT pCert = NULL;
  1191.  
  1192.   CRYPT_XML_BLOB encoded = { CRYPT_XML_CHARSET_AUTO, 0, NULL };
  1193.   CRYPT_XML_STATUS status;
  1194.  
  1195.   DWORD i, j, k;
  1196.  
  1197.   encoded.pbData = pbData;
  1198.   encoded.cbData = cbData;
  1199.  
  1200.   // Carrega a(s) assinatura(s) da cadeia XML
  1201.   if ((hr = CryptXmlOpenToDecode( NULL, 0, NULL, 0, &encoded, &hDoc )) != S_OK)
  1202.   {
  1203.     error( CertUtil_Win32FromHResult(hr), "Falha verificando arquivo XML",
  1204.         __FUNC__ "() : CryptXmlOpenToDecode()" );
  1205.     return false;
  1206.   }
  1207.  
  1208.   if ((hr = CryptXmlGetDocContext( hDoc, &pDoc )) != S_OK)
  1209.   {
  1210.     error( CertUtil_Win32FromHResult(hr), "Falha verificando arquivo XML",
  1211.         __FUNC__ "() : CryptXmlGetDocContext()" );
  1212.     CryptXmlClose( hDoc );
  1213.     return false;
  1214.   }
  1215.  
  1216.   if (pDoc->cSignature < 1)
  1217.   {
  1218.     error( 0, "O arquivo XML não tem assinatura", __FUNC__ "()" );
  1219.     CryptXmlClose( hDoc );
  1220.     return false;
  1221.   }
  1222.  
  1223.   // Verifica a(s) assinatura(s)
  1224.   for (i = 0; hr == S_OK && i < pDoc->cSignature; ++i)
  1225.   {
  1226.     // Localiza o certificado da assinatura
  1227.     for (j = 0; j < pDoc->rgpSignature[i]->pKeyInfo->cKeyInfo && hKey == NULL; ++j)
  1228.     {
  1229.       if (pDoc->rgpSignature[i]->pKeyInfo->rgKeyInfo[j].dwType == CRYPT_XML_KEYINFO_TYPE_X509DATA)
  1230.       {
  1231.         for (k = 0; k < pDoc->rgpSignature[i]->pKeyInfo->rgKeyInfo[j].X509Data.cX509Data; ++k)
  1232.         {
  1233.           CRYPT_XML_X509DATA_ITEM *pX
  1234.             = &pDoc->rgpSignature[i]->pKeyInfo->rgKeyInfo[j].X509Data.rgX509Data[k];
  1235.  
  1236.           if (pX->dwType == CRYPT_XML_X509DATA_TYPE_CERTIFICATE)
  1237.           {
  1238.             // Cria o contexto do certificado e importa a chave pública
  1239.             if ((pCert = CertCreateCertificateContext( X509_ASN_ENCODING,
  1240.                     pX->Certificate.pbData, pX->Certificate.cbData )) != NULL)
  1241.             {
  1242.               if (CryptImportPublicKeyInfoEx2(
  1243.                     X509_ASN_ENCODING, &pCert->pCertInfo->SubjectPublicKeyInfo,
  1244.                     CRYPT_OID_INFO_PUBKEY_SIGN_KEY_FLAG, NULL, &hKey ))
  1245.               {
  1246.                 hr = S_OK;
  1247.                 break;
  1248.               }
  1249.  
  1250.               hr = HRESULT_FROM_WIN32( GetLastError() );
  1251.  
  1252.               if (hKey != NULL)
  1253.               {
  1254.                 //BCryptDestroyKey( hKey ); // Requer Bcrypt.lib
  1255.                 hKey = NULL;
  1256.               }
  1257.  
  1258.               CertFreeCertificateContext( pCert );
  1259.               pCert = NULL;
  1260.             }
  1261.           }
  1262.           else
  1263.             hr = HRESULT_FROM_WIN32( GetLastError() );
  1264.         }
  1265.       }
  1266.     }
  1267.  
  1268.     if (hKey == NULL)
  1269.     {
  1270.       error( CertUtil_Win32FromHResult(hr),
  1271.           "Não foi possível localizar a chave pública no arquivo XML", __FUNC__ "()" );
  1272.       if (hr == S_OK)
  1273.         hr = S_FALSE;
  1274.       break;
  1275.     }
  1276.  
  1277.     // TODO: Verificar cadeia de certificados obtido via CertGetCertificateChain()
  1278.  
  1279.     // Valida a assinatura
  1280.     hr = CryptXmlVerifySignature( pDoc->rgpSignature[i]->hSignature, hKey, 0 );
  1281.  
  1282.     // Verifica a(s) referência(s)
  1283.     if (hr == S_OK)
  1284.     {
  1285.       hr = CryptXmlGetSignature( pDoc->rgpSignature[i]->hSignature, &pSig );
  1286.  
  1287.       for (j = 0; hr == S_OK && j < pSig->SignedInfo.cReference; ++j)
  1288.       {
  1289.         if ((hr = CryptXmlGetReference( pSig->SignedInfo.rgpReference[j]->hReference, &pRef)) != S_OK)
  1290.           break;
  1291.  
  1292.         memset( (void*)&status, '\0', sizeof(CRYPT_XML_STATUS) );
  1293.  
  1294.         if ((hr = CryptXmlGetStatus( pSig->SignedInfo.rgpReference[j]->hReference, &status )) != S_OK)
  1295.           break;
  1296.  
  1297.         if ((status.dwErrorStatus & CRYPT_XML_STATUS_ERROR_NOT_RESOLVED) != 0)
  1298.         {
  1299.           // TODO: Resolver referências externas ou não resolvidas
  1300.           // via HrSampleResolveExternalXmlReference, CryptXmlDigestReference e CryptXmlGetStatus
  1301.           hr = CRYPT_XML_E_UNRESOLVED_REFERENCE;
  1302.           break;
  1303.         }
  1304.         if ((status.dwErrorStatus & CRYPT_XML_STATUS_ERROR_DIGEST_INVALID) != 0)
  1305.         {
  1306.           hr = CRYPT_XML_E_INVALID_DIGEST;
  1307.           break;
  1308.         }
  1309.       }
  1310.     }
  1311.  
  1312.     // Verifica o resultado da assinatura
  1313.     if (hr == S_OK)
  1314.     {
  1315.       if ((hr = CryptXmlGetStatus( pDoc->rgpSignature[i]->hSignature, &status )) == S_OK)
  1316.       {
  1317.         if ((status.dwErrorStatus & CRYPT_XML_STATUS_ERROR_DIGEST_INVALID) != 0)
  1318.           hr = CRYPT_XML_E_INVALID_DIGEST;
  1319.  
  1320.         if ((status.dwErrorStatus & CRYPT_XML_STATUS_ERROR_NOT_RESOLVED) != 0)
  1321.           hr = CRYPT_XML_E_UNRESOLVED_REFERENCE;
  1322.       }
  1323.     }
  1324.  
  1325.     if (hKey != NULL)
  1326.     {
  1327.       //BCryptDestroyKey( hKey ); // Requer Bcrypt.lib
  1328.       hKey = NULL;
  1329.     }
  1330.  
  1331.     if (pCert != NULL)
  1332.     {
  1333.       CertFreeCertificateContext( pCert );
  1334.       pCert = NULL;
  1335.     }
  1336.   }
  1337.  
  1338.   if (hr != S_OK)
  1339.   {
  1340.     System::WideString ctx;
  1341.  
  1342.     if (hr == CRYPT_XML_E_INVALID_SIGNATURE)
  1343.       ctx = ":\nAssinatura inválida";
  1344.     else if (hr == CRYPT_XML_E_VERIFY_FAILED)
  1345.       ctx = ":\nAssinatura não confere";
  1346.     else if (hr == CRYPT_XML_E_INVALID_DIGEST)
  1347.       ctx = ":\nResumo (digest hash) não confere";
  1348.     else if (hr == CRYPT_XML_E_UNRESOLVED_REFERENCE)
  1349.       ctx = ":\nReferência não resolvida";
  1350.     else if ((hr & CRYPT_XML_E_BASE) == CRYPT_XML_E_BASE)
  1351.       ctx = ":\nErro do CryptXML nº " + IntToStr( (int)(hr & ~CRYPT_XML_E_BASE) );
  1352.  
  1353.     error( CertUtil_Win32FromHResult(hr), "Assinatura não validada" + ctx, __FUNC__ "()" );
  1354.   }
  1355.  
  1356.   CryptXmlClose( hDoc );
  1357.  
  1358.   return (hr == S_OK);
  1359. }
  1360.  
  1361. //---------------------------------------------------------------------------
  1362. // Nome do arquivo de certificados atual
  1363. //
  1364. System::WideString Cert::getFileName()
  1365. {
  1366.   return certFile;
  1367. }
  1368.  
  1369. //---------------------------------------------------------------------------
  1370. // Nome do certificado atual
  1371. //
  1372. System::WideString Cert::getCertName()
  1373. {
  1374.   return certName;
  1375. }
  1376.  
  1377. //---------------------------------------------------------------------------
  1378. // Tipo de certificado
  1379. //
  1380. System::WideString Cert::getCertType()
  1381. {
  1382.   return certType;
  1383. }
  1384.  
  1385. //---------------------------------------------------------------------------
  1386. // Nome Empresarial/Pessoa Física
  1387. //
  1388. System::WideString Cert::getName()
  1389. {
  1390.   return name;
  1391. }
  1392.  
  1393. //---------------------------------------------------------------------------
  1394. // Número de inscrição no CPF/CNPJ
  1395. //
  1396. System::WideString Cert::getDoc()
  1397. {
  1398.   return doc;
  1399. }
  1400.  
  1401. //---------------------------------------------------------------------------
  1402. // Localização
  1403. //
  1404. System::WideString Cert::getLoc()
  1405. {
  1406.   return loc;
  1407. }
  1408.  
  1409. //---------------------------------------------------------------------------
  1410. // E-mail do requerente
  1411. //
  1412. System::WideString Cert::getEmail()
  1413. {
  1414.   return email;
  1415. }
  1416.  
  1417. //---------------------------------------------------------------------------
  1418. // Data do início da validade
  1419. //
  1420. System::TDateTime Cert::getValidFrom()
  1421. {
  1422.   return validFrom;
  1423. }
  1424.  
  1425. //---------------------------------------------------------------------------
  1426. // Data do fim da validade
  1427. //
  1428. System::TDateTime Cert::getValidTo()
  1429. {
  1430.   return validTo;
  1431. }
  1432.  
  1433. //---------------------------------------------------------------------------
  1434. // Nome do emissor certificado
  1435. //
  1436. System::WideString Cert::getIssuerName()
  1437. {
  1438.   return issuerName;
  1439. }
  1440.  
  1441. //---------------------------------------------------------------------------
Advertisement
Add Comment
Please, Sign In to add comment