//------------------------------------------------------------------------------
// Tumar CSP
// Copyright (c) 2011 Scientific Lab. Gamma Technologies. All rights reserved.
// SDK
// Sign and create Signed PKCS-7 message
//------------------------------------------------------------------------------
#include "ex_util.h"
//------------------------------------------------------------------------------
#define PKCS7S_FILE "pkcs7_deg.bin"
#define CERT1 "us1.cer"
#define CERT2 "us2.cer"
#define P7_DATA "123"
//------------------------------------------------------------------------------
// Пользователь имеет контейнер с ключами на подпись и сертификатом
// Задача:
// 1. Создать дегеративный Signed PKCS-7 message с сертификатами
//------------------------------------------------------------------------------
unsigned char WBuf[8196];
unsigned char Cert1[8196];
unsigned char Cert2[8196];
unsigned char SN[128];
//------------------------------------------------------------------------------
int main(void)
{
 int code;
 HCRYPTPROV hProv=0;
 HCRYPTHASH hHash=0;
 HCRYPTKEY  hKey=0;
 DWORD dw,len,len2,sz1,sz2;

 // Загружаем криптопровайдер
 code=LoadTumarCSP((char*)CSP_LIB); if (code) {printf("Load CSP error: %d\n",code); return 1;}
 // Загружаем 1-й сертификат
 if (getFileLen(CERT1,     &sz1)) {printf("getFileLen error\r\n"); return 1;}
 if (readFile  (CERT1,Cert1,sz1)) {printf("readFile error\r\n");   return 1;}
 // Загружаем 2-й сертификат
 if (getFileLen(CERT2,     &sz2)) {printf("getFileLen error\r\n"); return 1;}
 if (readFile  (CERT2,Cert2,sz2)) {printf("readFile error\r\n");   return 1;}
 //
 // Создаем контекст CSP
 if (!CPAcquireContext(&hProv,NULL,CRYPT_VERIFYCONTEXT,NULL)) {
   printf("CPAcquireContext Error: %0X\n",GetLastErrorCSP(0));
   return 1;
 }
 // Создеем хэш-объект
 if (!CPCreateHash(hProv,CALG_TGR3411,0,0,&hHash)) {
   printf("CPCreateHash Error: %0X\n",GetLastErrorCSP(hProv));
   return 1;
 }
 // Добавляем сертификаты
 if (!CPSetHashParam(hProv,hHash,HP_PKCS7_CERTIFICATE,Cert1,0)) {
   printf("CPSetHashParam Error: %0X\n",GetLastErrorCSP(hProv));
   return 1;
 }
 if (!CPSetHashParam(hProv,hHash,HP_PKCS7_CERTIFICATE,Cert2,0)) {
   printf("CPSetHashParam Error: %0X\n",GetLastErrorCSP(hProv));
   return 1;
 }
 // Добавляем данные
 len=strlen(P7_DATA);
 if (!CPSetHashParam(hProv,hHash,HP_PKCS7_DATA_SIZE,(BYTE*)&len,0)) {
   printf("CPSetHashParam Error: %0X\n",GetLastErrorCSP(hProv));
   return 1;
 }
 if (!CPSetHashParam(hProv,hHash,HP_PKCS7_DATA,(BYTE*)P7_DATA,0)) {
   printf("CPSetHashParam Error: %0X\n",GetLastErrorCSP(hProv));
   return 1;
 }
 // Формируем PKCS7
 len=sizeof(WBuf);
 if (!CPSignHash(hProv,hHash,0,NULL,CRYPT_SIGN_PKCS7,WBuf,&len)) {
   printf("CPSignHash Error: %0X\n",GetLastErrorCSP(hProv));
   return 1;
 }
 // Сохраняем результат
 writeFile(PKCS7S_FILE,WBuf,len);
 CPDestroyHash(hProv,hHash);
 // Закрываем контекст CSP
 CPReleaseContext(hProv,0);
 //
 // Проверим результат
 //
 // Создаем контекст CSP
 if (!CPAcquireContext(&hProv,NULL,CRYPT_VERIFYCONTEXT,NULL)) {
   printf("CPAcquireContext Error: %0X\n",GetLastErrorCSP(0));
   return 1;
 }
 // Создеем хэш-объект
 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;
 }
 // Узнаем количество вложенных сертификатов
 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(Cert1);
   if (CPGetHashParam(hProv,hHash,HP_PKCS7_ENUM_CERT,Cert1,&len,CRYPT_FIRST)) {
     do {
       if (CPImportKey(hProv,Cert1,len,0,0,&hKey)) {
         len2=sizeof(SN);
         if (CPGetKeyParam(hProv,hKey,KP_KEY_SN,SN,&len2,0)) {
           printf("SN: %02X %02X ...\r\n",SN[0],SN[1]);
         }
         CPDestroyKey(hProv,hKey);
         hKey=0;
       }
       len=sizeof(Cert1);
     } while(CPGetHashParam(hProv,hHash,HP_PKCS7_ENUM_CERT,Cert1,&len,0));
   }
 }
 // Получаем данные
 len=sizeof(dw);
 if (!CPGetHashParam(hProv,hHash,HP_PKCS7_DATA_SIZE,(BYTE*)&dw,&len,0)) {
   printf("CPGetHashParam Error: %0X\n",GetLastErrorCSP(hProv));
   return 1;
 }
 if (dw) {
   len=sizeof(WBuf);
   if (!CPGetHashParam(hProv,hHash,HP_PKCS7_DATA,WBuf,&len,0)) {
     printf("CPGetHashParam Error: %0X\n",GetLastErrorCSP(hProv));
     return 1;
   }
   WBuf[dw]=0;
   printf("Data in pkcs7 : %s\n",(char*)WBuf);
 }
 CPDestroyHash(hProv,hHash);
 // Закрываем контекст CSP
 CPReleaseContext(hProv,0);
 printf("OK\n");
 return 0;
}
//------------------------------------------------------------------------------
