I'm trying to verify the certificate of an IRC server against the UTN_USERFirst_Hardware CA.
I'm running into error code 20 from SSL_get_verify_result
(which if I'm correct means that it failed to get the peer cert?).
Also, I'm not all too sure what the precedence of 'steps' is in the process.
Here is what I've cobbled together:
int tallis_ssl_verify(tallis_t *tallis, X509 *cert)
{
int rv;
X509_VERIFY_PARAM_set_hostflags(
tallis->param,
X509_CHECK_FLAG_NO_PARTIAL_WILDCARDS);
SSL_CTX_set_default_verify_paths(tallis->ssl_context);
ERR_clear_error();
rv = SSL_CTX_load_verify_locations(
tallis->ssl_context,
"/etc/ssl/certs/AddTrust_External_Root.pem",
"/etc/ssl/certs");
if (!rv)
{
fprintf(stderr, ERR_error_string(ERR_get_error(), NULL));
return 1;
}
X509_VERIFY_PARAM_set1_host(tallis->param, tallis->host, 0);
SSL_CTX_set_verify(tallis->ssl_context, SSL_VERIFY_PEER, NULL);
SSL_set_verify(tallis->ssl_connection, SSL_VERIFY_PEER, NULL);
ERR_clear_error();
rv = SSL_get_verify_result(tallis->ssl_connection);
if (rv != X509_V_OK)
{
printf("%d\n", rv);
fprintf(stderr, ERR_error_string(ERR_get_error(), NULL));
return 1;
}
ERR_clear_error();
X509_STORE_CTX *ctx = X509_STORE_CTX_new();
if (!ctx)
{
fprintf(stderr, ERR_error_string(ERR_get_error(), NULL));
return 1;
}
ERR_clear_error();
X509_STORE *store = X509_STORE_new();
if (!store)
{
X509_STORE_free(store);
fprintf(stderr, ERR_error_string(ERR_get_error(), NULL));
return 1;
}
ERR_clear_error();
rv = X509_STORE_CTX_init(ctx, store, cert, NULL);
if (!rv)
{
X509_STORE_free(store);
fprintf(stderr, ERR_error_string(ERR_get_error(), NULL));
return 1;
}
X509_STORE_set_flags(store, X509_V_FLAG_CB_ISSUER_CHECK);
X509_LOOKUP *lookup = X509_STORE_add_lookup(store, X509_LOOKUP_file());
X509_STORE_load_locations(
store,
"/etc/ssl/certs/AddTrust_External_Root.pem",
NULL);
X509_STORE_set_default_paths(store);
X509_LOOKUP_load_file(
lookup,
"/etc/ssl/certs/AddTrust_External_Root.pem",
X509_FILETYPE_PEM);
X509_STORE_add_cert(store, cert);
ERR_clear_error();
rv = X509_verify_cert(ctx);
if (rv != 1)
{
X509_STORE_free(store);
fprintf(
stderr,
"%s\n%s\n",
ERR_error_string(ERR_get_error(), NULL),
X509_verify_cert_error_string(ctx->error));
return 1;
}
return 0;
}
And the calling routine for context:
int main(int argc, char *argv[])
{
tallis_t *tallis = malloc(sizeof(tallis_t));
tallis->host = "irc.freenode.net";
tallis->port = "6697";
tallis->bio = NULL;
tallis->ssl_connection = NULL;
ssl_init(tallis->ssl_connection);
tallis->ssl_context = SSL_CTX_new(TLSv1_2_client_method());
tallis->ssl_connection = SSL_new(tallis->ssl_context);
tallis->param = SSL_get0_param(tallis->ssl_connection);
int rv;
rv = tallis_connect(tallis);
if (rv)
DIE("%s\n", "connection failed");
ERR_clear_error();
X509 *cert = SSL_get_peer_certificate(tallis->ssl_connection);
if (!cert)
DIE("%s\n", ERR_error_string(ERR_get_error(), NULL));
rv = tallis_ssl_verify(tallis, cert);
X509_free(cert);
if (rv)
DIE("%s\n", "certificate verificiation failed");
else
printf("%s\n", "certificate verification succeeded");
rv = tallis_loop(tallis);
if (rv)
DIE("%s\n", "socket connection terminated");
rv = ssl_shutdown(tallis);
if (rv)
DIE("%s\n", "ssl shutdown failed");
}
So, as it stands my flow is this: Establish connection at the socket (BIO) level -> call SSL_get_peer_certificate
-> do certificate verification, is this correct?
What's the difference between SSL_get_verify_result
and X509_verify_cert
and which one should be used first?
Sorry if this is too general, I need a little guidance and the docs are just manual pages with not much correlative information, I find it hard to get an organized view of OpenSSL.
How about 'How do I verify a peer certificate in OpenSSL as simply as possible?'