//------------------------------------------------------------------------------
// Tumar CSP
// Copyright (c) 2011 Scientific Lab. Gamma Technologies. All rights reserved.
// SDK
// Verify certificate
//------------------------------------------------------------------------------
#include "ex_util.h"
//------------------------------------------------------------------------------
//#define CMP_RA_CERT "cmp_ra.cer"
#define CMP_RA_CERT "ub.cer"
//------------------------------------------------------------------------------
unsigned char Cert[8196];
//------------------------------------------------------------------------------
// Пользователь имеет контейнер с установленными сертификтами УЦ
// Задача:
// 1. Проверить сертификат
//------------------------------------------------------------------------------
#define INIT_POLICIE "1.2.398.3.5.2.12" // Политика КЦМР о первичной инициализации
#define TEST_POLICIE "1.2.398.3.5.2.13" // Политика КЦМР о тестовых ключах
//------------------------------------------------------------------------------
int main(void)
{
 int code,i,is_init=0,is_test=0;
 HCRYPTPROV hProv=0;
 HCRYPTKEY  hKey =0;
 DWORD dw,len,sz;
 BYTE SN[64];
 char wb[256],x[8];
 CSP_ALG_OBJECT obj;
 ALG_ID ai=0;

 // Загружаем криптопровайдер
 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;}
 //
 // Создаем контекст CSP
 if (!CPAcquireContext(&hProv,(char*)CSP_PROF,0,NULL)) {
   printf("CPAcquireContext Error: %0X\n",GetLastErrorCSP(0));
   return 1;
 }
 // Загружаем проверяемый сертификат
 if (!CPImportKey(hProv,Cert,sz,0,0,&hKey)) {
   printf("CPImportKey Error: %0X\n",GetLastErrorCSP(hProv));
   return 1;
 }
 // Получим информацию о валидности
 len=sizeof(wb);
 if (!CPGetKeyParam(hProv,hKey,KP_CRT_VFROM,(BYTE*)wb,&len,0)) {
   printf("CPGetKeyParam KP_CRT_VFROM Error: %0X\n",GetLastErrorCSP(hProv));
   return 1;
 }
 printf("Validity from: %s\r\n",wb);
 len=sizeof(wb);
 if (!CPGetKeyParam(hProv,hKey,KP_CRT_VTO,(BYTE*)wb,&len,0)) {
   printf("CPGetKeyParam KP_CRT_VTO Error: %0X\n",GetLastErrorCSP(hProv));
   return 1;
 }
 printf("Validity to  : %s\r\n",wb);
 // Получим имя выпустившего сертификат
 len=sizeof(wb);
 if (!CPGetKeyParam(hProv,hKey,KP_CRT_ISSU_DN,(BYTE*)wb,&len,0)) {
   printf("CPGetKeyParam KP_CRT_ISSU_DN Error: %0X\n",GetLastErrorCSP(hProv));
   return 1;
 }
 printf("Issuer : %s\r\n",wb);
 // Получим имя владельца сертификата
 len=sizeof(wb);
 if (!CPGetKeyParam(hProv,hKey,KP_CRT_SUBJ_DN,(BYTE*)wb,&len,0)) {
   printf("CPGetKeyParam KP_CRT_SUBJ_DN Error: %0X\n",GetLastErrorCSP(hProv));
   return 1;
 }
 printf("Subject: %s\r\n",wb);
 // Получим серийный номер
 len=sizeof(SN);
 if (!CPGetKeyParam(hProv,hKey,KP_KEY_SN,SN,&len,0)) {
   printf("CPGetKeyParam KP_KEY_SN Error: %0X\n",GetLastErrorCSP(hProv));
   return 1;
 }
 wb[0]=0;
 for(i=0;i<(int)len;i++) {sprintf(x,"%02X",SN[i]); strcat(wb,x);}
 printf("SN: %s\r\n",wb);
 // Получим информацию об алгоритме ключа
 len=sizeof(ai);
 if (!CPGetKeyParam(hProv,hKey,KP_ALGID,(BYTE*)&ai,&len,0)) {
   printf("CPGetKeyParam KP_ALGID Error: %0X\n",GetLastErrorCSP(hProv));
   return 1;
 }
 len=sizeof(obj); i=0;
 if (CPGetProvParam(hProv,PP_ENUM_SIGN_KEY_ALG,(BYTE*)&obj,&len,CRYPT_FIRST))
   do {
     if (obj.ai==ai) {i=1; break;}
     len=sizeof(obj);
   } while(CPGetProvParam(hProv,PP_ENUM_SIGN_KEY_ALG,(BYTE*)&obj,&len,0));
 if (!i) {
   len=sizeof(obj);
   if (CPGetProvParam(hProv,PP_ENUM_EXCH_KEY_ALG,(BYTE*)&obj,&len,CRYPT_FIRST))
     do {
       if (obj.ai==ai) {i=1; break;}
       len=sizeof(obj);
     } while(CPGetProvParam(hProv,PP_ENUM_EXCH_KEY_ALG,(BYTE*)&obj,&len,0));
 }
 if (!i) printf("Error ALG_AD (%X)\r\n",ai);
 printf("Key OID: %s\r\n",obj.oid);
 printf("Key alg name: %s\r\n",obj.name);
 // Получим информацию о правах использования ключа
 dw=0; len=sizeof(dw);
 if (!CPGetKeyParam(hProv,hKey,KP_CRT_USAGE,(BYTE*)&dw,&len,0)) {
   printf("CPGetKeyParam KP_CRT_USAGE Error: %0X\n",GetLastErrorCSP(hProv));
   return 1;
 }
 // Можно ли использовать ключ для создания ЭЦП ?
 if (dw&(CRT_KEYUSAGE_DIGSIGN|CRT_KEYUSAGE_NONREPU)) printf("Use for signature OK (KEYUSAGE: %X)\r\n",dw);
 else                                                printf("Use for signature Error (KEYUSAGE: %X)\r\n",dw);
 // Получим информацию о полномочиях ключа
 dw=0; len=sizeof(dw);
 if (!CPGetKeyParam(hProv,hKey,KP_CRT_PURPOSES,(BYTE*)&dw,&len,0)) {
   printf("CPGetKeyParam KP_CRT_PURPOSES Error: %0X\n",GetLastErrorCSP(hProv));
   return 1;
 }
 // Можно ли использовать ключ, например, для подписи OCSP-ответов ?
 if (dw&CRT_PURPOSE_OCSP) printf("Use for OCSP sign OK (PURPOSES: %X)\r\n",dw);
 else                     printf("Use for OCSP sign Error (PURPOSES: %X)\r\n",dw);
 // Получим информацию о политиках сертификата
 len=sizeof(wb);
 if (CPGetKeyParam(hProv,hKey,KP_CRT_ENUM_POLICIES,(BYTE*)wb,&len,CRYPT_FIRST))
   do {
     printf("POLICIE: [%s]\r\n",wb);
     if (!strcmp(wb,INIT_POLICIE)) is_init++;
     if (!strcmp(wb,TEST_POLICIE)) is_test++;
     len=sizeof(wb);
   } while(CPGetKeyParam(hProv,hKey,KP_CRT_ENUM_POLICIES,(BYTE*)wb,&len,0));
 if (is_init || is_test) printf("Not use for real work!\r\n");
 // Закрываем контекст CSP
 CPReleaseContext(hProv,0);
 printf("OK\n");
 return 0;
}
//------------------------------------------------------------------------------
