Hi, I'm using the ASN1_item_d2i method for getting extension info out of an x509 certificate. It _appears_ that it's changing the dereferenced address of the 'in' parameter, even though it's supposed to be const. This can cause memory corruption later, as it seems that "in" usually corresponds to a member of the X509_EXTENSION struct (which needs to be freed later along with the X509 struct), at least in all of the example code that I've seen.
For reference, here's the method structure: ASN1_VALUE * ASN1_item_d2i(ASN1_VALUE **val, const unsigned char **in, long len, const ASN1_ITEM *it); I've attached an example program which demonstrates the problem (along with a demonstration of how to work around it). Here's the output that I get when I try both the default and the workaround: [EMAIL PROTECTED]:~$ g++ test.cc -o test `pkg-config --cflags --libs libcrypto libssl` [EMAIL PROTECTED]:~$ ./test test2.pem ext_value_data: 0x8056510 ext_value_data: 0x805654f [EMAIL PROTECTED]:~$ g++ test.cc -o test `pkg-config --cflags --libs libcrypto libssl` -DUSE_ALTERNATE_CAST [EMAIL PROTECTED]:~$ ./test test2.pem ext_value_data: 0x8056510 ext_value_data: 0x8056510 If you try to run the test program above through valgrind (when compiled without -DUSE_ALTERNATE_CAST), you get an error even if openssl is compiled with -DPURIFY. Would appreciate any insight as to whether this is expected or not. If it is expected, I must say that it's very confusing for a method to override the dereferenced value of a const pointer. Thanks! Will
#include <assert.h> #include <openssl/err.h> #include <openssl/pem.h> #include <openssl/pkcs12.h> #include <openssl/sha.h> #include <openssl/ssl.h> #include <openssl/x509.h> #include <openssl/x509v3.h> int main(int argc, char *argv[]) { SSL_library_init(); SSL_load_error_strings(); ERR_load_BIO_strings(); ERR_load_crypto_strings(); OpenSSL_add_all_algorithms(); OpenSSL_add_all_ciphers(); OpenSSL_add_all_digests(); BIO *bio = BIO_new(BIO_s_file()); if (BIO_read_filename(bio, argv[1]) <= 0) { printf("Can't read file.\n"); exit(-1); } X509 *cert = PEM_read_bio_X509(bio, NULL, NULL, NULL); BIO_free(bio); int index = X509_get_ext_by_NID(cert, NID_info_access, -1); assert(index >= 0); X509_EXTENSION *ext = X509_get_ext(cert, index); assert(ext); X509V3_EXT_METHOD *method = X509V3_EXT_get(ext); assert(method); void *ext_data = NULL; const unsigned char **ext_value_data; ext_value_data = (const_cast<const unsigned char **> (&ext->value->data)); const unsigned char *ext_value_data_1 = ext->value->data; assert(method->it); fprintf(stderr, "ext_value_data: %p\n", ext->value->data); #if USE_ALTERNATE_CAST ext_data = ASN1_item_d2i(NULL, &ext_value_data_1, ext->value->length, ASN1_ITEM_ptr(method->it)); #else ext_data = ASN1_item_d2i(NULL, ext_value_data, ext->value->length, ASN1_ITEM_ptr(method->it)); #endif fprintf(stderr, "ext_value_data: %p\n", ext->value->data); ASN1_item_free((ASN1_VALUE *)ext_data, ASN1_ITEM_ptr(method->it)); X509_free(cert); ERR_free_strings(); EVP_cleanup(); }
test2.pem
Description: application/x509-ca-cert
pgpVBPwGodQkR.pgp
Description: PGP signature