OpenSSL Verify Peer (Client) Certificate in C++

13,844

On the server, you must also call SSL_CTX_load_verify_locations(). This function tells the server what certificates to use for certificate verification; the SSL_CTX_set_client_CA_list() function sets the list of allowed CAs that are sent to the client in the handshake. Both are required.

(You also need a SSL_CTX_use_PrivateKey_file() call on the client, after the use_certificate_file call, but I guess you're doing that and just left it out).

Share:
13,844
Jason Champion
Author by

Jason Champion

I dig C++, Linux, Qt, wxWidgets, SDL2, Python, Django, and PostgreSQL. Interested in desktop audio software/tools.

Updated on June 14, 2022

Comments

  • Jason Champion
    Jason Champion almost 2 years

    I have a working application that establishes an SSL connection to a server. The server uses a self-signed certificate and the client loads a certificate authority chain to tell it that the server is OK to trust. I did that with code like this on the client:

    SSL_METHOD* method = TLSv1_client_method();
    _ctx = SSL_CTX_new(method);
    if ( SSL_CTX_load_verify_locations(_ctx, "ca-all.crt", NULL) != 1 )
    {
        return false;
    }
    _ssl = SSL_new(_ctx);
    int val = SSL_set_fd(_ssl, _socket->GetFD());
    if ( val != SSL_SUCCESS )
    {
        int err = SSL_get_error(_ssl, val);
        return false;
    }
    val = SSL_connect(_ssl);
    

    And on the server:

      if ( SSL_CTX_use_certificate_chain_file( g_ctx, "ca-chain1.crt" ) <= 0 ) {
        return 1;
      }
      ppem_file = getenv( "PEM_FILE" );
      if ( ppem_file == NULL ) {
        ppem_file = pem_file;
      }
      if ( SSL_CTX_use_certificate_file( g_ctx, ppem_file,
                                         SSL_FILETYPE_PEM ) <= 0 ) {
        return 1;
      }
      if ( SSL_CTX_use_PrivateKey_file( g_ctx, ppem_file,
                                        SSL_FILETYPE_PEM ) <= 0 ) {
        return 2;
      }
    

    I'm trying to modify this code so that the server also verifies the client's peer certificate (self-signed, using same issuer as the server) and having a bit of trouble. I haven't found good "conceptual overview" documentation anywhere, and that seems to be a typical hurdle with the OpenSSL libraries.

    On the client I added this after the SSL_CTX_load_verify_locations() call:

    if ( SSL_CTX_use_certificate_file(_ctx, "generic_client.pem", SSL_FILETYPE_PEM ) != 1 )
    {
        return false;
    }
    

    On the server I added this after the SSL_CTX_use_PrivateKey_file() call:

      STACK_OF(X509_NAME) *list;
      list = SSL_load_client_CA_file( "ca_chain2.crt" );
      if( list == NULL ) {
        return 4;
      }
      SSL_CTX_set_client_CA_list( g_ctx, list );
      SSL_CTX_set_verify( g_ctx, SSL_VERIFY_PEER, NULL );
    

    The connection fails because the certificate doesn't validate. The client seems to load the certificate fine and if I comment out the SSL_CTX_set_verify line, the client connects without trouble (because its certificate is never verified).

    It seems that the server doesn't think that the client's certificate authority chain is good. What am I missing here?

    From the commandline I can run: openssl verify -CAfile ca-chain2.crt generic_client.pem And it passes, so I have the right certificate data available, I must just be using it wrong somehow.

  • Jason Champion
    Jason Champion over 13 years
    Thank you, that was exactly what I needed.