Search code examples
csslopensslx509pem

Does correct freeing of X509 structures differ between chain and main certificate adding?


I need to add PEM type certificates from memory, which means I can't use the built in read-from-file helpers.

My problem is that there's no documentation on how to free up memory afterwards. Now my best guess is as follows:

SSL_CTX_use_certificate(): //X509 structure SHOULD be freed using X509_free(), as in     SSL_CTX_use_certificate_file()
SSL_CTX_use_PrivateKey()  // EVP_KEY structure SHOULD be freed using EVP_KEY_free(), as in     SSL_CTX_use_PrivateKey_file()
SSL_CTX_add_extra_chain_cert() // X509 structure SHOULD NOT be freed, as in SSL_CTX_use_certificate_chain_file()

And some time grepping the source seems to suggest that SSL_CTX_use_certificate() increments a reference count, whereas SSL_CTX_add_extra_chain_cert() doesn't.

Can anyone confirm or deny my suspicions?


Solution

  • Run this program with and without the X509_free under Valgrind.

    #include <stdio.h>
    #include <openssl/ssl.h>
    #include <openssl/err.h>
    #include <openssl/x509.h>
    
    int main(int argc, char* argv[])
    {
        unsigned long err;
    
        SSL_library_init();
        OpenSSL_add_all_algorithms();
    
        SSL_CTX* ctx = SSL_CTX_new(SSLv23_method());
        err = ERR_get_error();
        if(ctx == NULL)
        {
            printf("SSL_CTX_new failed: 0x%lx\n", err);
            exit (1);
        }
    
        X509* x509 = X509_new();
        err = ERR_get_error();
        if(x509 == NULL)
        {
            printf("X509_new failed: 0x%lx\n", err);
            exit (1);
        }
    
        long res = SSL_CTX_add_extra_chain_cert(ctx, x509);
        err = ERR_get_error();
        if(res != 1)
        {
            printf("SSL_CTX_add_extra_chain_cert failed: 0x%lx\n", err);
            exit (1);
        }
    
        X509_free(x509);
        SSL_CTX_free(ctx);
    
        return 0;
    }
    

    With the X509_free(x509) uncommented:

    $ valgrind ./openssl-test.exe
    ==23505== Memcheck, a memory error detector
    ==23505== Copyright (C) 2002-2013, and GNU GPL'd, by Julian Seward et al.
    ==23505== Using Valgrind-3.9.0 and LibVEX; rerun with -h for copyright info
    ==23505== Command: ./openssl-test.exe
    ==23505== 
    ==23505== WARNING: Support on MacOS 10.8 is experimental and mostly broken.
    ==23505== WARNING: Expect incorrect results, assertions and crashes.
    ==23505== WARNING: In particular, Memcheck on 32-bit programs will fail to
    ==23505== WARNING: detect any errors associated with heap-allocated data.
    ==23505== 
    ==23505== Invalid read of size 4
    ==23505==    at 0x100001AD9: CRYPTO_add_lock (in ./openssl-test.exe)
    ==23505==    by 0x1000BC62A: asn1_item_combine_free (in ./openssl-test.exe)
    ==23505==    by 0x1000BC5A6: ASN1_item_free (in ./openssl-test.exe)
    ==23505==    by 0x10009CC5F: sk_pop_free (in ./openssl-test.exe)
    ==23505==    by 0x100114862: SSL_CTX_free (in ./openssl-test.exe)
    ==23505==    by 0x100001213: main (openssl-test.c:43)
    ==23505==  Address 0x100202dac is 28 bytes inside a block of size 184 free'd
    ==23505==    at 0x7517: free (vg_replace_malloc.c:472)
    ==23505==    by 0x100002634: CRYPTO_free (in ./openssl-test.exe)
    ==23505==    by 0x1000BC95C: asn1_item_combine_free (in ./openssl-test.exe)
    ==23505==    by 0x1000BC5A6: ASN1_item_free (in ./openssl-test.exe)
    ==23505==    by 0x10000120A: main (openssl-test.c:42)
    ...