Verify certificate with OPENSSL and CryptoAPI

OPENSSL

Setps:

1, Input the encoded der certificate into X509 struct.

2, New a X509 store and input the root certificate.

3, Input encoded CRL into the store and set X509_V_FLAG_CRL_CHECK.

4, New a store context and input the root restore and subject certificate.

5, Call X509_verify_cert to verify the certificate. And the function also check CRL signature.

Here is the sample code:

/*

note: check certificate with OPENSSL

parameter:

    char *szRootFP, root CA certificate file path

    char *szCertFP, subject certificate file path

    char *szCRLFP, CRL file path

return:

    1, success

    0, error

*/

bool verify509Cert(unsigned char *bRoot, int iRootLen, unsigned char *bCert, int iCertLen, unsigned char *bCRL, int iCrlLen)

{

    int iRet = 0;

 

    X509_STORE_CTX *ctx = NULL;        // 证书存储区句柄

    X509 *usrCert = NULL;              //X509 证书结构体,保存用户证书

    X509 *caCert = NULL;            //X509 证书结构体,保存CA 证书

    X509 *rootCert = NULL;             //X509 证书结构体,保存根证书

    X509_CRL *Crl = NULL;              //X509_CRL 结构体,保存CRL

    STACK_OF(X509) *caCertStack = NULL;

    X509_STORE *rootCertStore = NULL;  // 证书存储区

 

    // DER 编码的根证书转化为X509 结构体

    rootCert = d2i_X509(NULL,(const unsigned char **)&bRoot,iRootLen);

    if (rootCert==NULL)

       return false ;

 

    // DER 编码的用户证书转化为X509 结构体

    usrCert = d2i_X509(NULL,(const unsigned char **)&bCert,iCertLen);

    if (usrCert==NULL)

       return false ;

   

 

    // 新建X509 证书存储区

    rootCertStore = X509_STORE_new();

    // 添加根证书到证书存储区

    X509_STORE_add_cert(rootCertStore,rootCert);

 

    // 设置检查CRL 标志位,如果设置此标志位,则检查CRL ,否则不检查CRL

    if (NULL != bCRL) {

       if (*bCRL != '/0') {

           // DER 编码的CRL 转化为X509_CRL 结构体

           Crl = d2i_X509_CRL(NULL,(const unsigned char **)&bCRL,iCrlLen);

           if (Crl==NULL) {

              X509_free(rootCert);

              return false ;

           }

           X509_STORE_set_flags(rootCertStore,X509_V_FLAG_CRL_CHECK);

           // 添加CRL 到证书存储区

           X509_STORE_add_crl(rootCertStore,Crl);

       }

    }

 

    // 新建证书存储区句柄

    ctx = X509_STORE_CTX_new();

    // 初始化根证书存储区、用户证书1

    iRet = X509_STORE_CTX_init(ctx,rootCertStore,usrCert,caCertStack);

    if (iRet != 1)

    {

       printf("X509_STORE_CTX_init err/n");

       X509_free(usrCert);

       X509_free(rootCert);

       X509_STORE_CTX_cleanup(ctx);

       X509_STORE_CTX_free(ctx);

       X509_STORE_free(rootCertStore);

       return false ;

    }

 

    // 验证用户证书

    iRet = X509_verify_cert(ctx);  

    if (iRet != 1)

    {

       printf("verify cer err.error= %d,info:%s/n",ctx->error,X509_verify_cert_error_string(ctx->error));

    }

 

    // 释放内存

    X509_free(usrCert);

    X509_free(rootCert);

    X509_STORE_CTX_cleanup(ctx);

    X509_STORE_CTX_free(ctx);

    X509_STORE_free(rootCertStore);

 

    return 1 == iRet ? true : false ;

}

 

 

CryptoAPI

To use CryptoAPI, we need to include "Wincrypt.h" and link to crypt32.lib first.

Steps to check certificate and CRL

1, Add rood certificate and CRL into one cert store,

2, Add subject certificate into a cert context.

3, Check cert by calling CertVerifySubjectCertificateContext().

By setting the flag we can check signature, RCL, and time:

      the flag can be the combination of

      CERT_STORE_REVOCATION_FLAG 0x04

      CERT_STORE_SIGNATURE_FLAG 0x01

      CERT_STORE_TIME_VALIDITY_FLAG 0x02

 

Here we need to note that the function return true no matter if the cert is valid. We need to check the validation of cert by checking returned flag value. If be checked OK the flag will be 0, otherwise the flag remain unchanged.

For example, to enable both signature and time validity, the value CERT_STORE_SIGNATURE_FLAG | CERT_STORE_TIME_VALIDITY_FLAG is placed in the pdwFlags DWORD value as an input parameter. If CERT_STORE_SIGNATURE_FLAG verification succeeds, but CERT_STORE_TIME_VALIDITY_FLAG verification fails, pdwFlags is set to CERT_STORE_TIME_VALIDITY_FLAG when the function returns.

 

If CERT_STORE_REVOCATION_FLAG was enabled and the issuer does not have a CRL in the store, then CERT_STORE_NO_CRL_FLAG is set in addition to CERT_STORE_REVOCATION_FLAG. //CERT_STORE_NO_CRL_FLAG 0x00010000

So if there is no CRL in store, we check a valid cert and we got the returned flag value 0x00010004, and we check a invalid subject certificate, the return value will be 0x00010005.

 

And here is the code of certificate checking function:


/*

notes: check certificate with CryptoAPI

parameter:

    char *szRootFP, root CA certificate file path

    char *szCertFP, subject certificate file path

    char *szCRLFP, CRL file path

return:

    1, success

    0, system error

   -1, invalid certificate

    4, revoked certificate

*/

int checkCert(char *szRootFP, char *szCertFP, char *szCRLFP)

{

    int iRet = 0;

    PCCERT_CONTEXT  pCertRootContext = NULL;

    PCCERT_CONTEXT  pCertContext = NULL;

    HCERTSTORE hMemStore = NULL;

 

    unsigned char usrCertificate[4096] = {0}; //DER 证书缓冲区数组

    unsigned long usrCertificateLen = 0;      // 证书长度

    unsigned char derCrl[4096] = {0};         //CRL 缓冲区数组

    unsigned long derCrlLen = 0;           //CRL 长度

    unsigned char derRootCert[4096] = {0}; // 根证书缓冲区数组

    unsigned long derRootCertLen = 0;      // 根证书长度

    DWORD dwFlags = 0; // flag for CertVerifySubjectCertificateContext

 

    // error check

    if (NULL == szRootFP || NULL == szCertFP)

       return false ;

 

    FILE *fp;

    // 读取根证书

    fp = fopen(szRootFP, "rb");

    if (fp==NULL)

       return false ;

    derRootCertLen = fread(derRootCert,1,sizeof (derRootCert),fp);

    fclose(fp);

 

    // 读取CRL 文件

    if (NULL != szCRLFP){

       if (*szCRLFP != '/0') {

           fp=fopen(szCRL,"rb");

           if (fp==NULL)

           {

              printf("open file err/n");

              return false ;

           }

           derCrlLen = fread(derCrl,1,sizeof (derCrl),fp);

           fclose(fp);

 

           dwFlags = CERT_STORE_REVOCATION_FLAG;

       }

    }

 

    // 读取待验证的用户证书

    fp=fopen(szCertFP,"rb");

    if (fp==NULL)

    {

       printf("open file err/n");

       return false ;

    }

    usrCertificateLen = fread(usrCertificate,1,sizeof (usrCertificate),fp);

    fclose(fp);

 

 

    // add subject cert to context

    pCertContext = CertCreateCertificateContext(

       MY_ENCODING_TYPE,   // Encoding type

       usrCertificate,      // Encoded data from the certificate retrieved

       usrCertificateLen);  // Length of the encoded data

    if (NULL == pCertContext)

       goto end;

 

 

    // add to root context

    // here we use store

    //pCertRootContext = CertCreateCertificateContext(

    //  MY_ENCODING_TYPE,   // Encoding type

    //  derRootCert,      // Encoded data from the certificate retrieved

    //  derRootCertLen);  // Length of the encoded data

    //if(NULL == pCertRootContext)

    //  goto end;

    //iRet = CertAddCertificateContextToStore(

    //  hMemStore,

    //  pCertRootContext,

    //  CERT_STORE_ADD_ALWAYS,

    //  &pStoreContext

    //);

    //if (iRet != true)

    //  goto end;

 

    hMemStore = CertOpenStore(

       CERT_STORE_PROV_MEMORY,   // the memory provider type

       0,                        // the encoding type is not needed

       NULL,                     // use the default HCRYPTPROV

       0,                        // accept the default dwFlags

       NULL                      // pvPara is not used

       );

    if (NULL == hMemStore)

       goto end;

 

    // add root cert

    iRet = CertAddEncodedCertificateToStore(

       hMemStore,

       MY_ENCODING_TYPE,

       derRootCert,

       derRootCertLen,

       CERT_STORE_ADD_ALWAYS,

       &pCertRootContext

       );

    if (iRet != true )

       goto end;

 

    // if need check RCL, go this way

    if (CERT_STORE_REVOCATION_FLAG == dwFlags){

 

       // add crl

       iRet = CertAddEncodedCRLToStore(

           hMemStore,

           MY_ENCODING_TYPE,

           derCrl,

           derCrlLen,

           CERT_STORE_ADD_ALWAYS,

           NULL

       );

       if (iRet != true )

           goto end;

    }

 

    // check the cert

    // the flag can be

    // CERT_STORE_REVOCATION_FLAG 0x04

    // CERT_STORE_SIGNATURE_FLAG 0x01

    // CERT_STORE_TIME_VALIDITY_FLAG 0x02

    dwFlags |= CERT_STORE_SIGNATURE_FLAG;// | CERT_STORE_REVOCATION_FLAG;

    iRet = CertVerifySubjectCertificateContext(

       pCertContext,

       pCertRootContext,

       &dwFlags

       );

end:

    // clean resource

    if (pCertContext)

       CertFreeCertificateContext(pCertContext);

    if (pCertRootContext)

       CertFreeCertificateContext(pCertRootContext);

    if (hMemStore)

       CertCloseStore(hMemStore, 0);

 

 

    // return result

    if (iRet != true )

       return false ;

    if (dwFlags != 0)

       return dwFlags == CERT_STORE_SIGNATURE_FLAG ? -1 : dwFlags;

 

    return true ;

}


We may also use the following functions to check CRL:

CertCreateCRLContext

CertIsValidCRLForCertificate

CertFindCertificateInCRL

We need to note that the function CertIsValidCRLForCertificate does not look for the certificate in the CRL, we need to call CryptVerifyCertificateSignature to check

CRL signature.

 

More detail of CryptoAPI check MSDN:

ms-help://MS.MSDNQTR.v80.en/MS.MSDN.v80/MS.WIN32COM.v10.en/seccrypto/security/cryptography_functions.htm#certificate_and_certificate_store_functions

 

By the way, all the test above is in windows platform, I will test in CE platform later.

 

 

 

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值