//------------------------------------------------------------------------------
// Tumar CSP
// Copyright (c) 2011 Scientific Lab. Gamma Technologies. All rights reserved.
// SDK
// Encrypt and create Enveloped PKCS-7 message
//------------------------------------------------------------------------------
#include "ex_util.h"
//------------------------------------------------------------------------------
#define PKCS7E_FILE "pkcs7_enc.bin"
#define CERT1 "us1.cer"
#define CERT2 "us2.cer"
#define CERT3 "us3.cer"
//------------------------------------------------------------------------------
unsigned char WBuf[8196];
unsigned char Cert1[8196];
unsigned char Cert2[8196];
unsigned char Cert3[8196];
//------------------------------------------------------------------------------
// Пользователь имеет 3 сертификата получателей
// Задача:
// 1. Зашифровать данные
// 2. Создать Enveloped PKCS-7 message для всех получателей
//------------------------------------------------------------------------------
char *Data_for_enc=(char*)"1234567890ABCD";
//------------------------------------------------------------------------------
int main(void)
{
 int code;
 HCRYPTPROV hProv=0;
 HCRYPTKEY hKey,hExpKey1,hExpKey2,hExpKey3;
 DWORD len,len2,sz1,sz2,sz3;
 unsigned char *res;

 // Загружаем криптопровайдер
 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;}
 // Загружаем сертификат 3-го получателя
 if (getFileLen(CERT3,     &sz3)) {printf("getFileLen error\r\n"); return 1;}
 if (readFile  (CERT3,Cert3,sz3)) {printf("readFile error\r\n");   return 1;}
 //
 // Создаем контекст CSP
 if (!CPAcquireContext(&hProv,NULL,CRYPT_VERIFYCONTEXT,NULL)) {
   printf("CPAcquireContext Error: %0X\n",GetLastErrorCSP(0));
   return 1;
 }
 // Устанавливаем ключ 1-го получателя
 if (!CPImportKey(hProv,Cert1,sz1,0,0,&hExpKey1)) {
   printf("CPImportKey Error: %0X\n",GetLastErrorCSP(hProv));
   return 1;
 }
 // Устанавливаем ключ 2-го получателя
 if (!CPImportKey(hProv,Cert2,sz2,0,0,&hExpKey2)) {
   printf("CPImportKey Error: %0X\n",GetLastErrorCSP(hProv));
   return 1;
 }
 // Устанавливаем ключ 3-го получателя
 if (!CPImportKey(hProv,Cert3,sz3,0,0,&hExpKey3)) {
   printf("CPImportKey Error: %0X\n",GetLastErrorCSP(hProv));
   return 1;
 }
 // Создаем сессионный ключ
// if (!CPGenKey(hProv,CALG_GOST,CRYPT_EXPORTABLE,&hKey)) {
 if (!CPGenKey(hProv,CALG_T3DES,CRYPT_EXPORTABLE,&hKey)) {
   printf("CPGenKey CALG_GOST Error: %0X\r\n",GetLastErrorCSP(hProv));
   return 1;
 }
 // Формируем PKCS7 для 1-го получателя
 if (!CPExportKey(hProv,hKey,hExpKey1,SIMPLEBLOB_P7,CRYPT_DEFAULT_MODE,NULL,&len)) {
   printf("CPExportKey SIMPLEBLOB_P7 1 Error: %0X\r\n",GetLastErrorCSP(hProv));
   return 1;
 }
 // Формируем PKCS7 для 2-х получателей
 if (!CPExportKey(hProv,hKey,hExpKey2,SIMPLEBLOB_P7,CRYPT_DEFAULT_MODE,NULL,&len)) {
   printf("CPExportKey SIMPLEBLOB_P7 2 Error: %0X\r\n",GetLastErrorCSP(hProv));
   return 1;
 }
 // Шифруем данные
 len =strlen(Data_for_enc);
 len2=sizeof(WBuf);
 memcpy(WBuf,Data_for_enc,len);
 if (!CPEncrypt(hProv,hKey,0,TRUE,0,WBuf,&len,len2)) {
   printf("CPEncrypt Error: %0X\r\n",GetLastErrorCSP(hProv));
   return 1;
 }
 // Если требуется вложить данные:
 // Устанавливаем размер данных для экспорта PKCS7
 if (!CPSetKeyParam(hProv,hKey,KP_PKCS7_DATA_SIZE,(BYTE*)&len,0)) {
   printf("CPSetKeyParam KP_PKCS7_DATA_SIZE Error: %0X\n",GetLastErrorCSP(hProv));
   return 1;
 }
 // Устанавливаем данные для экспорта PKCS7
 if (!CPSetKeyParam(hProv,hKey,KP_PKCS7_DATA,(BYTE*)WBuf,0)) {
   printf("CPSetKeyParam KP_PKCS7_DATA Error: %0X\n",GetLastErrorCSP(hProv));
   return 1;
 }
 //
 // Формируем PKCS7 для 3-х получателей
 if (!CPExportKey(hProv,hKey,hExpKey3,SIMPLEBLOB_P7,CRYPT_DEFAULT_MODE,NULL,&len)) {
   printf("CPExportKey SIMPLEBLOB_P7 3 Error: %0X\r\n",GetLastErrorCSP(hProv));
   return 1;
 }
 res=(unsigned char*)calloc(len,sizeof(unsigned char));
 // Формируем результат
 if (!CPExportKey(hProv,hKey,0,SIMPLEBLOB_P7,0,res,&len)) {
   printf("CPExportKey SIMPLEBLOB_P7 4 Error: %0X\r\n",GetLastErrorCSP(hProv));
   return 1;
 }
 // Сохраняем запрос
 writeFile(PKCS7E_FILE,res,len);
 free(res);
 CPDestroyKey(hProv,hKey);
 CPDestroyKey(hProv,hExpKey1);
 CPDestroyKey(hProv,hExpKey2);
 CPDestroyKey(hProv,hExpKey3);
 // Закрываем контекст CSP
 CPReleaseContext(hProv,0);
 printf("OK\n");
 return 0;
}
//------------------------------------------------------------------------------
