Hi,

I'm creating a client/server application with OpenSSL, using
self-signed certificates. The client and server shall verify
each other's certificate, and this works well, if I use certificate
files. Now I'd like to embed the CA certificate in the client's
code for easier installation. Hence I'm (naively?) looking for
a replacement of this line of code:

  SSL_CTX_load_verify_locations(ctx, "ca.crt", NULL);

where "ca.crt" is the CA's certificate file, and it is searched
for in the current working directory. This works well.

What I did:

I converted the file to a X509 certificate (see code below),
and tried to load it with:

  SSL_CTX_add_extra_chain_cert(ctx, Cert);

but when I call SSL_connect(), this fails with the following
output from ERR_print_errors_fp(stderr):

4860:error:14090086:SSL routines:SSL3_GET_SERVER_CERTIFICATE:certificate verify failed:s3_clnt.c:1059:

My conclusion is that the certificate chain is incomplete or
something went wrong, but I have no idea how to do it correctly.

Could anybody help how to do it, or does it not work as I
want to do it?

Please note that I removed all error checking and variable
declarations from the following code for brevity, in the hope
that someone can see an obvious fault. In the real code all
function calls are checked. Here is the shortened code:

<code>

  SSL_library_init();
  SSL_load_error_strings();
  meth = (SSL_METHOD*)TLSv1_method();
  ctx = SSL_CTX_new(meth);
  SSL_CTX_use_certificate_file(ctx, "client.crt", SSL_FILETYPE_PEM);
  SSL_CTX_use_PrivateKey_file(ctx, "client.key", SSL_FILETYPE_PEM);
  SSL_CTX_check_private_key(ctx);

#if ! EMBED_CA_CERT

  SSL_CTX_load_verify_locations(ctx, "ca.crt", NULL);

#else /* EMBED_CA_CERT */

  X509 *Cert = d2i_X509(NULL, &p_buf, sizeof(ca_cert_asn1));
  char *str = X509_NAME_oneline(X509_get_subject_name(Cert),0,0);
  printf ("subject: %s\n", str); /* [1] */
  SSL_CTX_add_extra_chain_cert(ctx, Cert);

#endif /* EMBED_CA_CERT */

  SSL_CTX_set_verify(ctx,SSL_VERIFY_PEER,NULL);
  SSL_CTX_set_verify_depth(ctx,1);

  ssl = SSL_new (ctx);
  sbio = BIO_new_socket(existing_socket, BIO_NOCLOSE);
  SSL_set_bio(ssl, sbio, sbio);

  SSL_connect(ssl); // breaks here if EMBED_CA_CERT = 1

  server_cert = SSL_get_peer_certificate (ssl);
  str = X509_NAME_oneline(X509_get_subject_name(server_cert),0,0);
  printf ("subject: %s\n", str);

</code>


Note that everything works fine if EMBED_CA_CERT is 0, but breaks
in SSL_connect() with the error shown above if EMBED_CA_CERT is 1.
The printf() marked with [1] displays correct data from the ca.crt
file.

FWIW: The conversion of the file ca.crt was done as follows:

openssl x509 -outform DER -in ca.crt \
 | od -t x1 | cut -b 8-99 | sed -e 's/ /,0x/g' \
 | sed -e '1,1s/^,/ /'

and the output is included between...

static unsigned char ca_cert_asn1 [] = {
 0x30,0x82,0x04,0x65,0x30,0x82, ... /* included data bytes */
};


Any help would be appreciated!

--
Regards
Albrecht

______________________________________________________________________
OpenSSL Project                                 http://www.openssl.org
User Support Mailing List                    openssl-users@openssl.org
Automated List Manager                           majord...@openssl.org

Reply via email to