Thread: SSL Certs won't verify.

  1. #1
    Registered User
    Join Date
    Mar 2017
    Posts
    26

    SSL Certs won't verify.

    I'm trying to get my head around Client/Server programming with the OpenSSL C API, I've managed to make requests and get the response on the client side, and there's no trouble when using my system CA bundle and connecting to Google for example, but when i create my own CA, and run a server using a certificate signed with an intermediate CA, i get the request on the server, and send a response, the client is getting that response but can't verify the certificate.

    Can someone point out what i might be doing wrong?

    Client side:
    Code:
    #include <stdio.h>
    #include <openssl/bio.h>
    #include <openssl/ssl.h>
    
    int main() {
        SSL_load_error_strings();
        ERR_load_BIO_strings();
        OpenSSL_add_all_algorithms();
    
        BIO * bio;
        SSL_CTX * ctx = SSL_CTX_new(SSLv23_client_method());
        SSL * ssl;
        char resp[4096];
    
        if(! SSL_CTX_load_verify_locations(ctx, "/root/Desktop/SSL/RootCA/RootCA.crt", NULL)) {
            printf("Error loading trust store!\n");
            return 0;
        }
    
        bio = BIO_new_ssl_connect(ctx);
        BIO_get_ssl(bio, & ssl);
        SSL_set_mode(ssl, SSL_MODE_AUTO_RETRY);
    
        BIO_set_conn_hostname(bio, "127.0.0.1:4433");
    
    
        if(BIO_do_connect(bio) <= 0) {
            printf("Error opening connection!\n");
            return 0;
        }
    
        if(SSL_get_verify_result(ssl) != X509_V_OK) {
            printf("Couldn't verify server certificate!\n");
            return 0;
        }
    
        if(BIO_write(bio, "GET / HTTP/1.1\n"
                "User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:52.0) Gecko/20100101 Firefox/52.0\n\n", 500) <= 0) {
            printf("Error writing to socket!");
        }
    
    
        if(BIO_read(bio, resp, sizeof(resp)) <= 0) {
            printf("Error reading from socket!");
        } else { printf("%s", resp); }
    
    
    
    
        SSL_CTX_free(ctx);
        BIO_free_all(bio);
    
        return 0;
    }

    Server side:
    Code:
    #include <stdio.h>
    #include <unistd.h>
    #include <sys/socket.h>
    #include <arpa/inet.h>
    #include <openssl/ssl.h>
    #include <openssl/err.h>
    
    int create_socket(int port) {
        int s;
        struct sockaddr_in addr;
    
        addr.sin_family = AF_INET;
        addr.sin_port = htons(port);
        addr.sin_addr.s_addr = htonl(INADDR_ANY);
    
        s = socket(AF_INET, SOCK_STREAM, 0);
        if (s < 0) {
            perror("Unable to create socket");
            exit(EXIT_FAILURE);
        }
    
        if (bind(s, (struct sockaddr*)&addr, sizeof(addr)) < 0) {
            perror("Unable to bind");
            exit(EXIT_FAILURE);
        }
    
        if (listen(s, 1) < 0) {
            perror("Unable to listen");
            exit(EXIT_FAILURE);
        }
    
        return s;
    }
    
    void init_openssl() {
        SSL_load_error_strings();
        OpenSSL_add_ssl_algorithms();
    }
    
    void cleanup_openssl() {
        EVP_cleanup();
    }
    
    SSL_CTX *create_context() {
        const SSL_METHOD *method;
        SSL_CTX *ctx;
    
        method = SSLv23_server_method();
    
        ctx = SSL_CTX_new(method);
        if (!ctx) {
            perror("Unable to create SSL context");
            ERR_print_errors_fp(stderr);
            exit(EXIT_FAILURE);
        }
    
        return ctx;
    }
    
    void configure_context(SSL_CTX *ctx) {
        SSL_CTX_set_ecdh_auto(ctx, 1);
    
        /* Set the key and cert */
        if (SSL_CTX_use_certificate_file(ctx, "/root/Desktop/SSL/Server/server.crt", SSL_FILETYPE_PEM) <= 0) {
            ERR_print_errors_fp(stderr);
            exit(EXIT_FAILURE);
        }
    
        if (SSL_CTX_use_PrivateKey_file(ctx, "/root/Desktop/SSL/Server/server.key", SSL_FILETYPE_PEM) <= 0 ) {
            ERR_print_errors_fp(stderr);
            exit(EXIT_FAILURE);
        }
    }
    
    int main(int argc, char **argv) {
        int sock;
        SSL_CTX *ctx;
    
        init_openssl();
        ctx = create_context();
    
        configure_context(ctx);
    
        sock = create_socket(4433);
    
        /* Handle connections */
        while(1) {
            struct sockaddr_in addr;
            uint len = sizeof(addr);
            SSL ........l;
            const char reply[] = "test\n";
    
            int client = accept(sock, (struct sockaddr*)&addr, &len);
            if (client < 0) {
                perror("Unable to accept");
                exit(EXIT_FAILURE);
            }
    
            ssl = SSL_new(ctx);
            SSL_set_fd(ssl, client);
    
            if (SSL_accept(ssl) <= 0) {
                ERR_print_errors_fp(stderr);
            }
            else {
                SSL_write(ssl, reply, sizeof(reply));
            }
    
            SSL_free(ssl);
            close(client);
        }
    
        close(sock);
        SSL_CTX_free(ctx);
        cleanup_openssl();
    }

    I have a directory called SSL inside that directory is 3 other folders:
    RootCA
    IntCA
    Server


    The process i used to create certificates is as follows, from within the SSL directory:

    openssl genrsa -out RootCA.key 4096

    openssl req -new -x509 -days 100000 -key RootCA.key -out RootCA.crt

    openssl genrsa -out IntCA.key 4096

    openssl req -new -key IntCA.key -out IntCA.csr

    openssl x509 -req -days 100000 -in IntCA.csr -CA RootCA.crt -CAkey RootCA.key -CAcreateserial -out IntCA.crt

    openssl genrsa -out server.key 4096

    openssl req -new -key server.key -out server.csr

    openssl x509 -req -in server.csr -CA IntCA.crt -CAkey IntCA.key -set_serial 01 -out server.crt -days 1000 -sha1

    mv RootCA.* RootCA; mv IntCA.* IntCA; mv server.* Server



    At this point i'm not sure if it's a problem with the way certificates have been created or an issue with the code, most of which was basically from ibm.com examples and the server is a mixture of code snippets.
    Last edited by Strobez; 08-17-2017 at 10:28 PM. Reason: typo

  2. #2
    Lurking whiteflags's Avatar
    Join Date
    Apr 2006
    Location
    United States
    Posts
    9,612
    Have you imported your CA into your browser(s) and told them that you trust them? Self signed certificates aren't considered safe for the internet so most clients would bark (like a browser).

    Also you can do it in one line:
    Code:
     openssl req -x509 -newkey rsa:4096 -keyout key.pem -out cert.pem -days 365

  3. #3
    Registered User
    Join Date
    Mar 2017
    Posts
    26
    I'm using OpenSSL C API for both client and server. After using openssl s_client -connect localhost:4433 -CAfile /path/to/ca.crt in the terminal, it shows there is a problem with chain of trust. I guessed that means i need to create a CA bundle with both Root and Intermediate certificates. So i tried that, but now it's telling me it's an invalid CA certificate.
    I'm fairly sure the CA bundle is correct but i could be wrong.. Is there some way in OpenSSL to chose a bundle instead of a single certificate, or is it the same?
    If there's not meant to be a change in the code then it's possible something is wrong with the way i have created the bundle.crt file.

  4. #4
    Lurking whiteflags's Avatar
    Join Date
    Apr 2006
    Location
    United States
    Posts
    9,612
    I didn't promise that there wouldn't be changes to the code. There are examples online of how to verify certs with OpenSSL. Maybe you just haven't read far enough into the resource that you are using, but OpenSSL tends to involve many functions. I strongly suspect the example that you've cobbled together was never meant to validate anything. So, even a negative response is expected, in this case. Validation from the server code involves a handful of functions that you aren't using: certverify.c - example 'C' code for certificate validation

    Note in this example how CA_bundlestr[] was used, among other things.

  5. #5
    Registered User
    Join Date
    Mar 2017
    Posts
    26
    I removed the Intermediate CA and signed the server cert directly with the RootCA, then used RootCA to verify the server.
    It now works, however not as i'd hoped.
    For now i guess it's not a C programming question, but if anyone has any suggestions as to what went wrong, feel free to leave them here.
    Any time i try load a Ca bundle with more than one CA cert, i get errors.

  6. #6
    Registered User
    Join Date
    Mar 2017
    Posts
    26
    I posted below, it's working when i remove the Intermediate cert from the picture. Any ideas why i can't verify the while chain? I'm fairly sure the bundle file was okay.

  7. #7
    Registered User
    Join Date
    Mar 2017
    Posts
    26
    Turns out there was a problem with how the certificates were created. I followed another guide to create RootCA and IntCA, signed the server cert using IntCA, created a bundle using RootCA.crt and IntCA.crt, now it's working as expected.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. matrix nxn with verify
    By Angela Santoro in forum C++ Programming
    Replies: 16
    Last Post: 05-04-2016, 01:50 PM
  2. How To Get HR and VERIFY
    By EverydayDiesel in forum C++ Programming
    Replies: 1
    Last Post: 01-19-2014, 08:51 PM
  3. verify EOF
    By threahdead in forum C Programming
    Replies: 1
    Last Post: 10-11-2002, 07:49 AM
  4. verify input
    By Unregistered in forum C Programming
    Replies: 5
    Last Post: 05-23-2002, 05:38 PM

Tags for this Thread