简体   繁体   中英

OpenSSL: server cannot verify client certificate

I am working with a legacy OpenSSL wrapper, which I intend to extend with client certificates. This wrapper contains both server and client parts, but the issue is related only to server handshake part. The problem I am facing is that the server cannot get the certificate from client.

Here are the commands which I used to generate a pair of certificates for client and server:

1) Generate Certificate Authority:
openssl req -out ca.pem -new -x509

2) Generate server certificate:
openssl genrsa -out server.key 1024
openssl req -key server.key -new -out server.req
echo "00" > file.srl
openssl x509 -req -in server.req -CA ca.pem -CAkey privkey.pem -CAserial file.srl -out server.pem

3) Generate client certificate:
openssl genrsa -out client.key 1024
openssl req -key client.key -new -out client.req
openssl x509 -req -in client.req -CA ca.pem -CAkey privkey.pem -CAserial file.srl -out client.pem

All of the certificates are placed in one folder

When I am trying to connect to server implemented by Wrapper using s_client , I got the following output:

$ openssl s_client -connect localhost:40912 -CAfile ca.pem -cert client.pem -key client.key -state

CONNECTED(00000003)
SSL_connect:before/connect initialization
SSL_connect:unknown state
SSL_connect:SSLv3 read server hello A
depth=1 C = RO, ST = Rootville, L = Rootbirgem, O = CA Limited, OU = Issuer, CN = Autorida, emailAddress = ca@ca.mil
verify return:1
depth=0 C = SR, ST = Serverstan, L = Serversaintsburg, O = Servers advanced productions, OU = Acceptors factory, CN = Servstian, emailAddress = server@internet.org
verify return:1
SSL_connect:SSLv3 read server certificate A
SSL_connect:SSLv3 read server certificate request A
SSL_connect:SSLv3 read server done A
SSL_connect:SSLv3 write client certificate A
SSL_connect:SSLv3 write client key exchange A
SSL_connect:SSLv3 write certificate verify A
SSL_connect:SSLv3 write change cipher spec A
SSL_connect:SSLv3 write finished A
SSL_connect:SSLv3 flush data
SSL3 alert read:fatal:unknown CA
SSL_connect:failed in SSLv3 read server session ticket A
3073885884:error:14094418:SSL routines:SSL3_READ_BYTES:tlsv1 alert unknown ca:s3_pkt.c:1262:SSL alert number 48
3073885884:error:140790E5:SSL routines:SSL23_WRITE:ssl handshake failure:s23_lib.c:177:
---
Certificate chain
 0 s:/C=SR/ST=Serverstan/L=Serversaintsburg/O=Servers advanced productions/OU=Acceptors factory/CN=Servstian/emailAddress=server@internet.org
   i:/C=RO/ST=Rootville/L=Rootbirgem/O=CA Limited/OU=Issuer/CN=Autorida/emailAddress=ca@ca.mil
---
Server certificate
-----BEGIN CERTIFICATE-----
MIIDMzCCAhsCAQIwDQYJKoZIhvcNAQELBQAwgYkxCzAJBgNVBAYTAlJPMRIwEAYD
VQQIDAlSb290dmlsbGUxEzARBgNVBAcMClJvb3RiaXJnZW0xEzARBgNVBAoMCkNB
IExpbWl0ZWQxDzANBgNVBAsMBklzc3VlcjERMA8GA1UEAwwIQXV0b3JpZGExGDAW
BgkqhkiG9w0BCQEWCWNhQGNhLm1pbDAeFw0xNTEwMjcxNTA3MjlaFw0xNTExMjYx
NTA3MjlaMIG4MQswCQYDVQQGEwJTUjETMBEGA1UECAwKU2VydmVyc3RhbjEZMBcG
A1UEBwwQU2VydmVyc2FpbnRzYnVyZzElMCMGA1UECgwcU2VydmVycyBhZHZhbmNl
ZCBwcm9kdWN0aW9uczEaMBgGA1UECwwRQWNjZXB0b3JzIGZhY3RvcnkxEjAQBgNV
BAMMCVNlcnZzdGlhbjEiMCAGCSqGSIb3DQEJARYTc2VydmVyQGludGVybmV0Lm9y
ZzCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAy6j9ZHv/xCOqrRUXbWTE2Xht
PRPf/70Rytri4McCyjT6AO/GrDlAfD815yZPqTssRWy13sJGczoM4CPOffR7ufQR
4oMfugbX0W6kqlN7K1VpPlqtm8fb2jei5K0+tXOb7UHox13b69y0kVvArfhcUqmE
SGllcB++/Se2IIdcCOECAwEAATANBgkqhkiG9w0BAQsFAAOCAQEA5Eot8mv6QXvG
jd8oeX/JmJzzPSOn6kGMRsyR06OnF4tALHo5EdHaTF4EBgylVuAIp7dBRrdHzU4y
XnsY+X8lPlFEUFsSEuheJmISJgKZ8GtlbjHkV2cgXFSsFeiiI6Gjzlj2aOzYQQHD
DtpOL4InjHgeDTv7JxtMZXRaQqSvIejVXki0d+FOP42H3GyqleYABDtPl7o3gOmh
b8I7aZaOj/qxR8J//nGjXmodGHmL+RKK3vJ3thgD5UWREdE87qygJ2sZEUvXsnhG
CTulJEdWShGw27xuYw26wCt2yo0VXLcYsMgJLOjUAEdW3k+TowTi4XmZN4MaudAp
KFMlb2y7jg==
-----END CERTIFICATE-----
subject=/C=SR/ST=Serverstan/L=Serversaintsburg/O=Servers advanced productions/OU=Acceptors factory/CN=Servstian/emailAddress=server@internet.org
issuer=/C=RO/ST=Rootville/L=Rootbirgem/O=CA Limited/OU=Issuer/CN=Autorida/emailAddress=ca@ca.mil
---
Acceptable client certificate CA names
/C=RO/ST=Rootville/L=Rootbirgem/O=CA Limited/OU=Issuer/CN=Autorida/emailAddress=ca@ca.mil
---
SSL handshake has read 1101 bytes and written 2149 bytes
---
New, TLSv1/SSLv3, Cipher is AES256-GCM-SHA384
Server public key is 1024 bit
Secure Renegotiation IS supported
Compression: NONE
Expansion: NONE
SSL-Session:
    Protocol  : TLSv1.2
    Cipher    : AES256-GCM-SHA384
    Session-ID: 
    Session-ID-ctx: 
    Master-Key: 4CA603347F386EB0A723BCF1F07040E0C47FAD52AE9CBCC5DCB3D329D69C8E3FB31E994DC24FBA9E8312A476A8F08905
    Key-Arg   : None
    PSK identity: None
    PSK identity hint: None
    SRP username: None
    Start Time: 1445977139
    Timeout   : 300 (sec)
    Verify return code: 0 (ok)
---

At the same time on server part SSL_accept returns -1, SSL_get_error then returns SSL_ERROR_SSL and ERR_print_errors_fp gives me a message

3080665920:error:140890B2:SSL routines:SSL3_GET_CLIENT_CERTIFICATE:no certificate returned:s3_srvr.c:3279:

I don't have any experience with cryptography or OpenSSL , so all of these errors seems really confusing for me. OpenSSL 's documentation doesn't make things clear at all.

As far as I can see from s_client log, the problems is with certificates themselves, although I don't understand what exactly goes wrong. At the same time, I can successfully use these certificates with s_server application, so this is reproducible only with my implementation of server. It seems that my implementation is incomplete in some way, but I don't see a way how I can resolve the situation from here, most of the documents I found on the web avoid client certificates topic at all, and all of the error messages are cryptic.

Here's aa simplified code of the server (with omitted error checking, logging, timeouts, etc):

ctx_ = SSL_CTX_new(SSLv23_server_method());
SSL_CTX_use_certificate_file(ctx_, config.cert_file.c_str(), SSL_FILETYPE_PEM);
SSL_CTX_use_PrivateKey_file(ctx_, config.private_key.c_str(), SSL_FILETYPE_PEM);
if( !SSL_CTX_check_private_key(ctx_) )
{ /* never happens */ }

ssl_ = SSL_new(ctx_);

STACK_OF(X509_NAME)* list;
list = SSL_load_client_CA_file(config.client_ca_file.c_str());
SSL_set_client_CA_list(ssl_, list);
SSL_set_verify(ssl_, SSL_VERIFY_PEER, 0);

int flags = fcntl(fd_, F_GETFL, 0);
flags |= O_NONBLOCK;
if( fcntl(fd_, F_SETFL, flags) < 0 )

SSL_set_fd(ssl_, fd_);

while( /* not timeout */ )
{
    int res = SSL_accept(ssl_);
    if( res > 0) {break;}
    ec = WaitAfterError(res, /* timeout */);
    if( !ec.isSucceeded() )
    {
        return; // Returns here
    }
}

Wait after error have the following implementation:

ErrorCode OpenSslWrapper::WaitAfterError( int res, long* ptimeout )
{
    ErrorCode ec;
    int ret = SSL_get_error(ssl_, res);
    switch( ret )
    {
    case SSL_ERROR_WANT_READ:
        WaitForFd(fd_, Consts::k_WaitRead, ptimeout);
        return ec;
    case SSL_ERROR_WANT_WRITE:
    case SSL_ERROR_WANT_CONNECT:
    case SSL_ERROR_WANT_ACCEPT:
        WaitForFd(fd_, Consts::k_WaitWrite, ptimeout);
        return ec;
    case SSL_ERROR_SYSCALL:
        if( !errno ) {return ec;}
    case SSL_ERROR_SSL:
        // Got message here:
        ERR_print_errors_fp(stderr);
        ec = ErrorCode::Fail;
        return ec;
    default:
        ec = ERR_reason_error_string(ret);
        return ec;
    }
}

WaitForFd is just a simple wrapper over select.

The documentation for SSL_CTX_set_client_CA_list() says:

The CAs listed do not become trusted ( list only contains the names, not the complete certificates); use SSL_CTX_load_verify_locations to additionally load them for verification.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM