//------------------------------------------------------------------------------
// Tumar CSP
// Copyright (c) 2011 Scientific Lab. Gamma Technologies. All rights reserved.
// SDK
// Create RR CMP Request
//------------------------------------------------------------------------------
#include "ex_util.h"
//------------------------------------------------------------------------------
#define CMP_RR_FILE "cmp_rr.bin"
#define CMP_RA_CERT "cmp_ra.cer"
#define CMP_KUR_CERT "kur.cer"
//------------------------------------------------------------------------------
unsigned char WBuf[8196];
unsigned char Cert[8196];
unsigned char CerU[8196];
//------------------------------------------------------------------------------
// Пользователь имеет ключ на подпись с установленным сертификтом
// Задача:
// 1. Создать запрос на на отзыв сертификата в формате CMP/RR, защищенный подписью
//------------------------------------------------------------------------------
int main(void)
{
 int code;
 HCRYPTPROV hProv=0;
 HCRYPTKEY hKey,hExpKey,hKeyRR;
 DWORD dw,len,sz,sk;

 // Загружаем криптопровайдер
 code=LoadTumarCSP((char*)CSP_LIB); if (code) {printf("Load CSP error: %d\n",code); return 1;}
 //
 // Загружаем сертификат получателя (если имеется)
 if (getFileLen(CMP_RA_CERT,    &sz)) {printf("getFileLen error\r\n"); return 1;}
 if (readFile  (CMP_RA_CERT,Cert,sz)) {printf("readFile error\r\n");   return 1;}
 // Загружаем сертификат RR
 if (getFileLen(CMP_KUR_CERT,    &sk)) {printf("getFileLen error\r\n"); return 1;}
 if (readFile  (CMP_KUR_CERT,CerU,sk)) {printf("readFile error\r\n");   return 1;}
 //
 // Создаем контекст CSP
 if (!CPAcquireContext(&hProv,(char*)CSP_PROF,0,NULL)) {
   printf("CPAcquireContext Error: %0X\n",GetLastErrorCSP(0));
   return 1;
 }
 // Получим отзываемый на подпись
 if (!CPGetUserKey(hProv,AT_SIGNATURE,&hKey)) {
   printf("CPGetUserKey AT_SIGNATURE Error: %0X\n",GetLastErrorCSP(hProv));
   return 1;
 }
 // Создаем ключ экспорта запроса CMP/RR
 if (!CPGenKey(hProv,CALG_CMP_KEY,CRYPT_EXPORTABLE,&hExpKey)) {
   printf("CPGenKey CALG_CMP_KEY Error: %0X\r\n",GetLastErrorCSP(hProv));
   return 1;
 }
 // Устанавливаем тип сообщения (отзыв)
 dw=PKI_CMP_RR;
 if (!CPSetKeyParam(hProv,hExpKey,KP_CMP_TYPE,(BYTE*)&dw,0)) {
   printf("CPSetKeyParam KP_CMP_TYPE Error: %0X\n",GetLastErrorCSP(hProv));
   return 1;
 }
 // Устанавливаем причину отзыва (компрментация ключа)
 dw=REASON_keyCompromise;
 if (!CPSetKeyParam(hProv,hExpKey,KP_CMP_RR_REASON,(BYTE*)&dw,0)) {
   printf("CPSetKeyParam KP_CMP_RR_REASON Error: %0X\n",GetLastErrorCSP(hProv));
   return 1;
 }
 // Устанавливаем ключ подписи
 if (!CPSetKeyParam(hProv,hExpKey,KP_CMP_EXP_KEY,(BYTE*)&hKey,0)) {
   printf("CPSetKeyParam KP_CMP_EXP_KEY Error: %0X\n",GetLastErrorCSP(hProv));
   return 1;
 }
 // Устанавливаем сертификат получателя (если имеется)
 if (!CPSetKeyParam(hProv,hExpKey,KP_CMP_RCP_SUBJ,Cert,0)) {
   printf("CPSetKeyParam KP_CMP_RCP_SUBJ Error: %0X\n",GetLastErrorCSP(hProv));
   return 1;
 }
 // Импортируем отзываемый сертификат
 if (!CPImportKey(hProv,CerU,sk,0,0,&hKeyRR)) {
   printf("CPImportKey Error: %0X\n",GetLastErrorCSP(hProv));
   return 1;
 }
 
 // Добавляем еще ключ в запрос
 if (!CPSetKeyParam(hProv,hExpKey,KP_CMP_ADD_KEY,(BYTE*)&hKeyRR,0)) {
   printf("CPSetKeyParam KP_CMP_ADD_KEY Error: %0X\n",GetLastErrorCSP(hProv));
   return 1;
 }
 // Формируем запрос
 len=sizeof(WBuf);
 if (!CPExportKey(hProv,/*hKey*/0,hExpKey,PUBLICKEYBLOB_CMP,0,WBuf,&len)) {
   printf("CPExportKey PUBLICKEYBLOB_CMP Error: %0X\r\n",GetLastErrorCSP(hProv));
   return 1;
 }
 // Сохраняем запрос
 writeFile(CMP_RR_FILE,WBuf,len);
 //
 CPDestroyKey(hProv,hKey);
 CPDestroyKey(hProv,hExpKey);
 //
 // Проверим полученный запрос
 if (!CPImportKey(hProv,WBuf,len,0,0,&hKey)) {
   printf("CPImportKey Error: %0X\n",GetLastErrorCSP(hProv));
   return 1;
 }
 // Узнаем transactionID сформированного запроса
 len=sizeof(WBuf);
 if (!CPGetKeyParam(hProv,hKey,KP_CMP_TRANS_ID,WBuf,&len,0)) {
   printf("CPGetKeyParam KP_CMP_TRANS_ID Error: %0X\n",GetLastErrorCSP(hProv));
   return 1;
 }
 WBuf[len]=0;
 printf("transactionID = %s\n",(char*)WBuf);
 CPDestroyKey(hProv,hKey);
 // Закрываем контекст CSP
 CPReleaseContext(hProv,0);
 printf("OK\n");
 return 0;
}
//------------------------------------------------------------------------------
