-->

Verifying SSL client authenticity fails due to SSL

2020-07-30 03:45发布

问题:

I am using OpenSSL API for C++. Communication is between an embedded linux device (SSL server) and Windows software (SSL client).

I want to ensure that the intended server and client will only speak to one another. I have generated a root key for the server, along with the following:

  • Root CA (used by client to authorize server)
  • server certificate
  • server private key

My SSL connection works fine when only authorizing the server certificate during handshaking.

However, I also want to verify client authenticity, so I generated another root key for the client, along with the following:

  • Root CA (used by server to authorize client)
  • client certificate
  • client private key

Using the code below, my server fails to accept the client connection due to the following error:

724428760:error:140890B2:SSL routines:SSL3_GET_CLIENT_CERTIFICATE:no certificate returned:s3_srvr.c:3291:

Here is my server code related to SSL certificates:

bool SSLServer::loadCertificates(const char * sCertFile,
                                 const char * sKeyFile,
                                 const char * sCAFile)
{
    // set server certificate
    if (SSL_CTX_use_certificate_file(_pCTX, sCertFile, SSL_FILETYPE_PEM) <= 0)
    {
        ERR_print_errors_fp(stderr);
        return false;
    }

    // set the private key
    if (SSL_CTX_use_PrivateKey_file(_pCTX, sKeyFile, SSL_FILETYPE_PEM) <= 0)
    {
        ERR_print_errors_fp(stderr);
        return false;
    }

    // verify private key
    if (!SSL_CTX_check_private_key(_pCTX))
    {
        qWarning() << "Private key does not match the public certificate.";
        return false;
    }

    SSL_CTX_set_verify(_pCTX, SSL_VERIFY_PEER|SSL_VERIFY_FAIL_IF_NO_PEER_CERT, NULL);

    // load the trusted client CA certificate into context
    if (SSL_CTX_load_verify_locations(_pCTX, sCAFile, NULL) != 1)
    {
        ERR_print_errors_fp(stderr);
        return false;
    }

    // allow this CA to be sent to the client during handshake
    STACK_OF(X509_NAME) * list = SSL_load_client_CA_file(sCAFile);
    if (NULL == list)
    {
        qWarning() << "Failed to load SSL client CA file.";
        return false;
    }
    SSL_CTX_set_client_CA_list(_pCTX, list);
    SSL_CTX_set_verify_depth(_pCTX, 1);

    return true;
}

And here is my client code:

bool SSLClient::LoadCertificates(const char * sCAFile,
                                 const char * sClientCertFile,
                                 const char * sClientKeyFile)
{
    ASSERT(NULL != sCAFile && NULL != sClientCertFile && NULL != sClientKeyFile);

    // load RSA CA certificate into context to let client verify server's authenticity
    // (will be used with server certificate and private key)
    if (!SSL_CTX_load_verify_locations(_pCTX, sCAFile, NULL))
    {
        ERR_print_errors_fp(stderr);
        return false;
    }

    // load client certificate into context to let server verify client's authenticity
    // (will be used with server's RSA CA certificate)
    if (SSL_CTX_use_certificate_file(_pCTX, sClientCertFile, SSL_FILETYPE_PEM) != 1)
    {
        ERR_print_errors_fp(stderr);
        return false;
    }

    // load client certificate private key into context
    if (SSL_CTX_use_PrivateKey_file(_pCTX, sClientKeyFile, SSL_FILETYPE_PEM) != 1)
    {
        ERR_print_errors_fp(stderr);
        return false;
    }

    // verify that client cert and private key match
    if (!SSL_CTX_check_private_key(_pCTX))
    {
        OutputDebugString("Private key does not match the certificate public key\n");
        return false;
    }

    // require server certificate verification
    SSL_CTX_set_verify(_pCTX, SSL_VERIFY_PEER|SSL_VERIFY_FAIL_IF_NO_PEER_CERT, NULL);
    SSL_CTX_set_verify_depth(_pCTX, 1);

    return true;
}

Again, it works completely fine if I remove the code related to verifying client certificate. Am I missing something, or doing something completely wrong?

回答1:

Working copy of your code along with certificates: http://files.webfile.ru/567c28b8973091cbdad036f3e43e989b

Exactly your problem can be reproduced if generate certificates just hitting 'enter' answering questions. You'll got 'self-signed' certificate without any intention to make it. Problem exactly like OpenSSL - error 18 at 0 depth lookup:self signed certificate When snooping ssl problems you should use not wireshark but ssldump.



回答2:

724428760:error:140890B2:SSL routines:SSL3_GET_CLIENT_CERTIFICATE:no certificate returned:s3_srvr.c:3291:

The error message is misleading. While it says that the client did not return any certificates it happens also, if the client sends a certificate which the server can not validate. Please make sure, that the certificate sent by the client can actually be verified against the servers sCAFile.



标签: c++ ssl openssl