Hi,

I think there is somewhat strange behaviour in OpenSSL that causes
interesting bugs to happen when trying to encode CRLs based on deltas.
More information about the issue (causing a segfault under certain
conditions) is in the attached mail by Felix who discovered it.

Regards,
BenBE.
--- Begin Message ---
Hi,

I am trying to encode deltas between CRLs directly in ASN1 (DER), which works quite fine. Thereby I stumbled across a problem with encoding X509_ALGORS to ASN1:

I want to encode a new CRL's (X509_CRL_new), currently invalid, Signing algorithm (i2d_X509_ALGOR( crl->siging_alg, ... ) ) and restore that with "d2i_X509_ALGOR( &crl->signing_alg, ...)" afterwards. Restoring of the algorithm works fine in OpenSSL 1.0.1.f, but fails in OpenSSL 1.0.1j and 1.0.1l. This is probably because the "i2d" function encodes the (invalid) Signing algorithms slightly different in the different versions. This happens, because the invalid signing algorithm is represented slightly different in the internal structure. In version 1.0.1f the invalid algorithm is encoded as sequence with an object id with length 1 and content "00" ( -> 30 03 06 01 00). In the newer versions (1.0.1j and 1.0.1l) the invalid algorithm gets encoded as sequence with an object id of length 0 ( -> 30 02 06 00). This new encoding causes the "d2i" function to fail. Now the "d2i" function nulls the "sig_alg". This causes a "X509_CRL_verify" to cause a segfault.

Is this behavior expected? Am I doing something wrong? Is there a problem with what "X509_CRL_new" does (setting different "UNDEFINED"-ObjectId-Objects)? For better clarifying my problem, I have attached a small example code that creates such a CRL, tries to verify it (what will fail, but not crash), does the i2d, d2i re-setting of the Algorithm and re-calls X509_CRL_verify which now crashes in 1.0.1j and 1.0.1l, but works fine in 1.0.1.f.

For executing the sample, compile it with something like "gcc -g -std=c99 crl.c $YOUR_LIBCRYPTO" and attach the version of "libcrypto" you want to test with.
The example should segfault with 1.0.1j and 1.0.1l but run fine with 1.0.1f.

Thank you very much for your help,
Kind regards,
Felix

#include <openssl/ssl.h>
#include <openssl/err.h>
#include <stdio.h>

int main( int argc, char *argv[] ) {
    ERR_load_crypto_strings();

    // Generate some Public key
    EVP_PKEY_CTX *ctx;
    EVP_PKEY *pkey = NULL;
    ctx = EVP_PKEY_CTX_new_id(EVP_PKEY_RSA, NULL);
    if (!ctx)
        exit(-1);
    if (EVP_PKEY_keygen_init(ctx) <= 0)
        exit(-1);
    if (EVP_PKEY_CTX_set_rsa_keygen_bits(ctx, 2048) <= 0)
        exit(-1);
    if (EVP_PKEY_keygen(ctx, &pkey) <= 0)
        exit(-1);

    // Generate a new CRL
    X509_CRL *crl  = X509_CRL_new();
    unsigned char buffer[256];
    unsigned char *pos = buffer;
    // DER encode its X509 ALGORITHM
    i2d_X509_ALGOR( crl->sig_alg, &pos);
    printf("output: %d\n", (int) ( pos - buffer) );

    ERR_print_errors_fp(stdout);
    // Verification fails (but does not crash)
    int i = X509_CRL_verify( crl, pkey );
    printf("verify: %d\n", i);
    ERR_print_errors_fp(stdout);

    for( int i = 0; i< 5;i++){
        printf("%x ", (unsigned int) buffer[i] );
    }
    printf("\n");
    printf("%x\n", (unsigned int) crl->sig_alg->algorithm);
    const unsigned char *pos2 = buffer;
    // This is the broken output of openssl 1.0.1j, 1.0.1l and correct (30 02 
06 01 00) in 1.0.1f
    /*buffer[0] = 0x30;
    buffer[1] = 0x02;
    buffer[2] = 0x06;
    buffer[3] = 0x00;*/

    ERR_print_errors_fp(stdout);
    d2i_X509_ALGOR( &crl->sig_alg, &pos2, 9); // this nulls crl->sig_alg with 
the broken output see above
    printf("%d\n", (int) ( pos2 - buffer) );

    i = X509_CRL_verify( crl, pkey ); // this finally crashes in 1.0.1j, 1.0.1l 
but works great in 1.0.1.f
    printf("verify: %d\n", i);


    // Free things, if the program is still running.
    ERR_print_errors_fp(stdout);
    EVP_PKEY_free( pkey );
    EVP_PKEY_CTX_free( ctx );
    X509_CRL_free( crl );
}


--- End Message ---

Attachment: signature.asc
Description: OpenPGP digital signature

_______________________________________________
openssl-dev mailing list
To unsubscribe: https://mta.openssl.org/mailman/listinfo/openssl-dev

Reply via email to