//------------------------------------------------------------------------------
// Tumar CSP
// Copyright (c) 2011 Scientific Lab. Gamma Technologies. All rights reserved.
// SDK
// Verify Signature PKCS-7 message
//------------------------------------------------------------------------------
#include "ex_util.h"
//------------------------------------------------------------------------------
#define PKCS7S_FILE "pkcs7_sig.bin"
#define CMP_RA_CERT "us3.cer"
char *Data_for_sign=(char*)"1234567890ABCD";
//------------------------------------------------------------------------------
// Пользователь имеет сертификат подписавшего
// Задача:
// 1. Проверить ЭЦП в формате PKCS#7
//------------------------------------------------------------------------------
unsigned char WBuf[8196];
unsigned char Cert[8196],SN1[128],SN2[128];
char DN[512];
//------------------------------------------------------------------------------
int main(void)
{
 int code;
 HCRYPTPROV hProv=0;
 HCRYPTKEY  hKey=0;
 HCRYPTHASH hHash=0;
 DWORD len,dw,len1,len2,sz;
 ObjectInfoStr_t p7i;
 
 // Загружаем криптопровайдер
 code=LoadTumarCSP((char*)CSP_LIB); if (code) {printf("Load CSP error: %d\n",code); return 1;}
 //
 // Загружаем PKCS7
 if (getFileLen(PKCS7S_FILE,    &sz)) {printf("getFileLen error\r\n"); return 1;}
 if (readFile  (PKCS7S_FILE,WBuf,sz)) {printf("readFile error\r\n");   return 1;}
 //
 // Создаем контекст CSP
 if (!CPAcquireContext(&hProv,NULL,CRYPT_VERIFYCONTEXT,NULL)) {
   printf("CPAcquireContext Error: %0X\n",GetLastErrorCSP(0));
   return 1;
 }
 len=sizeof(p7i);
 p7i.object.pbData=WBuf;
 p7i.object.cbData=sz;
 if (!CPGetProvParam(hProv,PP_PKCS7_CONTENT_OID,(BYTE*)&p7i,&len,0)) {
   printf("CPGetProvParam Error: %0X\n",GetLastErrorCSP(hProv));
   return 1;
 }
 printf("CONTENT_OID: [%s]\r\n",p7i.data);
 // Создеем хэш-объект
 if (!CPCreateHash(hProv,CALG_TGR3411,0,0,&hHash)) {
   printf("CPCreateHash Error: %0X\n",GetLastErrorCSP(hProv));
   return 1;
 }
 // Установим проверяемый PKCS7
 if (!CPSetHashParam(hProv,hHash,HP_PKCS7_BODY,WBuf,0)) {
   printf("CPSetHashParam Error: %0X\n",GetLastErrorCSP(hProv));
   return 1;
 }
 // Хэшируем данные
 if (!CPHashData(hProv,hHash,(BYTE*)Data_for_sign,strlen(Data_for_sign),0)) {
   printf("CPHashData Error: %0X\n",GetLastErrorCSP(hProv));
   return 1;
 }
 // Узнаем серийный номер сертификата подриси документа
 len1=sizeof(SN1);
 if (!CPGetHashParam(hProv,hHash,HP_PKCS7_SI_SN,SN1,&len1,0)) {
   printf("CPGetHashParam Error: %0X\n",GetLastErrorCSP(hProv));
   return 1;
 }
 printf("SN (size=%d) : %02X %02X ...\r\n",len1,SN1[0],SN1[1]);
 // Узнаем количество вложенных сертификатов
 len=sizeof(dw);
 if (!CPGetHashParam(hProv,hHash,HP_PKCS7_CRT_COUNT,(BYTE*)&dw,&len,0)) {
   printf("CPGetHashParam Error: %0X\n",GetLastErrorCSP(hProv));
   return 1;
 }
 printf("Certificates count in pkcs7 : %d\n",dw);
 if (dw) {
   // Найдем сертификат, которым подписан этот документ
   len=sizeof(Cert);
   if (CPGetHashParam(hProv,hHash,HP_PKCS7_ENUM_CERT,Cert,&len,CRYPT_FIRST)) {
     do {
       if (CPImportKey(hProv,Cert,len,0,0,&hKey)) {
         len2=sizeof(SN2);
         if (CPGetKeyParam(hProv,hKey,KP_KEY_SN,SN2,&len2,0)) {
           if (len1==len2 && !memcmp(SN1,SN2,len1)) break;
         }
         CPDestroyKey(hProv,hKey);
         hKey=0;
       }
       len=sizeof(Cert);
     } while(CPGetHashParam(hProv,hHash,HP_PKCS7_ENUM_CERT,Cert,&len,0));
   }
 }
 if (!hKey) { // Сертификт не найден
   // Узнаем DN-имя подписавшего
   len=sizeof(DN);
   if (!CPGetHashParam(hProv,hHash,HP_PKCS7_SI_DN,(BYTE*)DN,&len,0)) {
     printf("CPGetHashParam Error: %0X\n",GetLastErrorCSP(hProv));
     return 1;
   }
   printf("DN : [%s]\n",DN);
   // Получаем сертификат другим методом, зная серийный номер и DN-имя
   // В примере, просто прочитаем из файла:
   if (getFileLen(CMP_RA_CERT,    &len)) {printf("getFileLen error\r\n"); return 1;}
   if (readFile  (CMP_RA_CERT,Cert,len)) {printf("readFile error\r\n");   return 1;}
   if (!CPImportKey(hProv,Cert,len,0,0,&hKey)) {
     printf("CPImportKey Error: %0X\n",GetLastErrorCSP(hProv));
     return 1;
   }
 }
 // Проверяем подпись
 if (!CPVerifySignature(hProv,hHash,WBuf,sz,hKey,0,0)) {
   printf("CPVerifySignature Error: %0X\n",GetLastErrorCSP(hProv));
   return 1;
 }
 CPDestroyHash(hProv,hHash);
 CPDestroyKey (hProv,hKey);
 // Закрываем контекст CSP
 CPReleaseContext(hProv,0);
 printf("OK\n");
 return 0;
}
//------------------------------------------------------------------------------
