tokafr
tokafr

Reputation: 119

How to verify intermediate CA

I have SSL connection to server. I had root CA and it was also the server certificate. I don't have a client certificate, when connection starts client verifies the server certificate and if it's valid connects. Now I've created Intermediate CA from my root CA, and replace it as server certificate, now I want the client to verify if the server certificate is trusted by root CA, I do it in C++ with openSSL API. how can I do it? here is what i've tried but it needs something more.

  const Char *caCert = "/home/omar/CA/host/host_rsa_key.crt";

      X509_LOOKUP *lookup = X509_STORE_add_lookup(ctx_ ->  cert_store,X509_LOOKUP_file());


      result=X509_LOOKUP_load_file(lookup,caCert,X509_FILETYPE_PEM);
      if(result != 1)
      {
        log()<<ERROR! Cannot load file to lookup structure\n";
        return;
      }


      SSL_CTX_sess_set_new_cb(ctx_, handshakeCallback);

      SSL_CTX_set_verify(ctx_, SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT,
                         verifyCallback);
      SSL_CTX_set_verify_depth(ctx_, 8);

this is where I load all certificate into ssl_ctx.

I have verifyCallback function which calls verifyCertificate() method here it is

  Int verifyCertificate(Int preverify, X509_STORE_CTX *store)
  {
  X509 *cert = NULL;
 // X509_NAME *name = NULL;

  SSL *ssl = NULL;

 Int certDepth = -1;
 Int certErr   = 0;

 Char *certHost = NULL;
 Char *certHash = NULL;
 Char *certData = NULL;


 cert = X509_STORE_CTX_get_current_cert(store);

 if (cert == NULL)

 log() << " ERROR! Failed to get certificate.\n";


goto VerifyCertificateError;
}



 certDepth = X509_STORE_CTX_get_error_depth(store);
 certErr = X509_STORE_CTX_get_error(store);



ssl = (SSL *) X509_STORE_CTX_get_ex_data(store, SSL_get_ex_data_X509_STORE_CTX_idx());

if (ssl == NULL)
{
 log() <<  ERROR! Failed to get SSL context from store context.\n";

 goto VerifyCertificateError;
}

if (preverify == 0)
{
//
// Self signed certificate allowed, SSH host auth style.
//

if (certErr == X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT)
{

  log() << " Certificate preverify failed on self";

  return 1;
}
else if (certErr == X509_V_ERR_CERT_NOT_YET_VALID)
{

  log() << Allowing not yet valid certificate.\n";

  return 1;
 }
 else if (certErr == X509_V_ERR_CERT_HAS_EXPIRED)
 {

  log() << " Allowing expired certificate.\n";


  return 1;
}
else if(certErr == X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT)
{

  log()<<" Unable to get issuer cert.\n"


  return 1;
}


if (certDepth == 0)
{
 if (parseCertificate(store, certHost, certHash, certData) == 0)
 {
   log() << "Encryptable: ERROR! Failed to parse certificate.\n";
  goto VerifyCertificateError;
}


  goto VerifyCertificateError;
}


if (authCallback_(certHost, certHash, certData, certCallback_,
                      callbackParameter_) == 0)
 {

  log() << " ERROR! Failed to authorize "
        << "the server certificate.\n";

  goto VerifyCertificateError;


if (certData != NULL)
{
  delete [] certData;
}

return 0;
}

Upvotes: 1

Views: 1576

Answers (1)

Steffen Ullrich
Steffen Ullrich

Reputation: 123561

Intermediate certificates are checked by OpenSSL and there is nothing special you need to do. Of course

  • you still have to specify your trust anchors (which you do)
  • the peer must provide the intermediate certificates in the handshake

You don't need a verify_callback because the default callback does the verification already, that is it checks the whole trust chain, including the intermediate certificates. If you still use one, preverify contains the result of the checks OpenSSL is doing already and your verification callback should just return this value unless you have specific cases where you need the verification to behave differently.

Upvotes: 1

Related Questions