//------------------------------------------------------------------------------
// Tumar CSP
// Copyright (c) 2011 Scientific Lab. Gamma Technologies. All rights reserved.
// SDK
// Verify IP CMP Response and get certificates
//------------------------------------------------------------------------------
#include "ex_util.h"
//------------------------------------------------------------------------------
#define CMP_IP_FILE   "cmp_ip.bin"
#define CMP_CRTS_FILE "cmp_crts.p7b"
#define CMP_CAS_FILE  "cmp_cas.p7b"
//------------------------------------------------------------------------------
unsigned char WBuf[8196];
//------------------------------------------------------------------------------
// Пользователь получил ответ CMP-сервера на запрос CMP/IR
// Задача:
// 1. Проверить полученный ответ
// 2. Просмотреть полученные сертификаты
//------------------------------------------------------------------------------
int main(void)
{
 int i,code;
 HCRYPTPROV hProv=0;
 HCRYPTKEY hKey=0,hKeyC;
 DWORD len,dw,type,sz;

 // Загружаем криптопровайдер
 code=LoadTumarCSP((char*)CSP_LIB); if (code) {printf("Load CSP error: %d\n",code); return 1;}
 //
 // Загружаем ответ сервера
 if (getFileLen(CMP_IP_FILE,    &sz)) {printf("getFileLen error\r\n"); return 1;}
 if (readFile  (CMP_IP_FILE,WBuf,sz)) {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 (!CPImportKey(hProv,WBuf,sz,0,0,&hKey)) {
   printf("CPImportKey Error: %0X\n",GetLastErrorCSP(hProv));
   return 1;
 }
 // Узнаем тип ответа
 len=sizeof(type);
 if (!CPGetKeyParam(hProv,hKey,KP_CMP_TYPE,(BYTE*)&type,&len,0)) {
   printf("CPGetKeyParam KP_CMP_TYPE Error: %0X\n",GetLastErrorCSP(hProv));
   return 1;
 }
 // Сервер прислал ответ об ошибке обработки
 if (type==PKI_CMP_ERROR) {
   len=sizeof(dw);
   if (!CPGetKeyParam(hProv,hKey,KP_CMP_STATUS,(BYTE*)&dw,&len,0)) {
     printf("CPGetKeyParam KP_CMP_STATUS Error: %0X\n",GetLastErrorCSP(hProv));
     return 1;
   }
   printf("PKI_CMP_ERROR, STATUS: %d (%s)\n",dw,code2status(dw));
   dw=0xFF;
   len=sizeof(dw);
   if (!CPGetKeyParam(hProv,hKey,KP_CMP_FAIL,(BYTE*)&dw,&len,0)) {
     printf("CPGetKeyParam KP_CMP_FAIL Error: %0X\n",GetLastErrorCSP(hProv));
     return 1;
   }
   if (dw!=0xFF) printf("FAIL: %d (%s)\n",dw,code2fail(dw));
   return 1;
 }
 // Сервер прислал ответ неправильного типа
 if (type!=PKI_CMP_IP) {
   printf("Unknown CMP TYPE\n");
   return 1;
 }
 // Просмотрм сертификаты ответа:
 for(i=0;i<3;i++) {
   dw=(DWORD)i;
   switch(dw) {
     case CRT_SECTION_EXT : printf("CRT_SECTION_EXT:\r\n");  break;
     case CRT_SECTION_USER: printf("CRT_SECTION_USER:\r\n"); break;
     case CRT_SECTION_CA  : printf("CRT_SECTION_CA:\r\n");   break;
   }
   if (!CPSetKeyParam(hProv,hKey,KP_CUR_CRT_SECTION,(BYTE*)&dw,0)) {
     printf("CPSetKeyParam KP_CUR_CRT_SECTION Error: %0X\n",GetLastErrorCSP(hProv));
     return 1;
   }
   len=sizeof(dw);
   if (!CPGetKeyParam(hProv,hKey,KP_CRT_COUNT,(BYTE*)&dw,&len,0)) {
     printf("CPGetKeyParam KP_CRT_COUNT Error: %0X\n",GetLastErrorCSP(hProv));
     return 1;
   }
   printf("Count certificates: %d\n",dw);
   if (dw) {
     len=sizeof(WBuf);
     if (CPGetKeyParam(hProv,hKey,KP_ENUM_CERT,WBuf,&len,CRYPT_FIRST)) {
       do {
         if (CPImportKey(hProv,WBuf,len,0,0,&hKeyC)) {
           len=sizeof(WBuf);
           if (CPGetKeyParam(hProv,hKeyC,KP_KEY_SN,WBuf,&len,0)) {
             printf("SN: %02X %02X ...\r\n",WBuf[0],WBuf[1]);
           }
           CPDestroyKey(hProv,hKeyC);
           hKeyC=0;
         }
         len=sizeof(WBuf);
       } while(CPGetKeyParam(hProv,hKey,KP_ENUM_CERT,WBuf,&len,0));
     }
   }
 }
 // Сохраним выпущенные сертификты в файл в формате PKCS#7
 len=sizeof(WBuf);
 if (CPGetKeyParam(hProv,hKey,KP_CMP_CERTIFICATES,WBuf,&len,0)) {
   printf("CPGetKeyParam KP_CMP_CERTIFICATES Error: %0X\n",GetLastErrorCSP(hProv));
   return 1;
 }
 writeFile(CMP_CRTS_FILE,WBuf,len);
 // Сохраним сертификты УЦ в файл в формате PKCS#7
 len=sizeof(WBuf);
 if (CPGetKeyParam(hProv,hKey,KP_CMP_CERTIFICATES_CA,WBuf,&len,0)) {
   printf("CPGetKeyParam KP_CMP_CERTIFICATES_CA Error: %0X\n",GetLastErrorCSP(hProv));
   return 1;
 }
 writeFile(CMP_CAS_FILE,WBuf,len);
 CPDestroyKey(hProv,hKey);
 // Закрываем контекст CSP
 CPReleaseContext(hProv,0);
 printf("OK\n");
 return 0;
}
//------------------------------------------------------------------------------
