How to properly create an RSA key from raw data in OpenSSL 3.0 in C language?
Asked Answered
C

1

5

i'm fairly new to OpenSSL and my current task at work is updating the code of a project from OpenSSL 1.1.1 to OpenSSL 3.0 and I'm stuck on a really weird problem.

I'm trying to create an RSA key from given raw data, precisely binary modulus and exponent that are converted to BIGNUM. I've tried to make it as it is described in the manual and the key creation works, but the problem is whatever I try to do with that key (or CTX based on it) fails, whether it's signature decryption or verification.

Here's the code where I create the key:

    /* function set up above */
    ctx = EVP_PKEY_CTX_new_from_name(NULL, "RSA", NULL);
    if ( ctx == NULL) {
        ERROR("Error: failed to initialize CTX from name.\n");
        goto OPENSSL_ERROR;
    }

    modulus = BN_bin2bn(pubkey->data, pubkey->size, NULL);
    exponent = BN_bin2bn(exp_arr, 3, NULL);
    if ( modulus == NULL || exponent == NULL ) {
        goto OPENSSL_ERROR;
    }

    OSSL_PARAM params[] = {
        OSSL_PARAM_BN("n", &modulus, BN_num_bytes(modulus)*8),
        OSSL_PARAM_BN("e", &exponent, BN_num_bytes(exponent)*8),
        OSSL_PARAM_BN("d", NULL, 0),
        OSSL_PARAM_END
    };

    status = EVP_PKEY_fromdata_init(ctx);
    if ( status <= 0 ) {
        ERROR("Error: failed to initialize key creation.\n");
        goto OPENSSL_ERROR;
    }

    status = EVP_PKEY_fromdata(ctx, &evp_key, EVP_PKEY_PUBLIC_KEY, params);
    if ( status <= 0 || evp_key == NULL ) {
        ERROR("Error: failed to create key.\n");
        goto OPENSSL_ERROR;
    }
    /* goes on to decrypt signature and later verify it against data - both fail */

It goes through swiftly, but trying to do whatever with that key or CTX based on that key fails miserably. I tried creating CTX with EVP_PKEY_CTX_new_id(), but it changed nothing. I tried omitting the parameter "d", but it changed nothing.

If anyone knows what I'm doing wrong and what should be changed - all help will be greatly appreciated.

P.S.

  1. pubkey is passed to the function as argument, data is a binary array, size is obviously it's size (size_t)
  2. the params given to the key are the same as in the previous version of the code which used the RSA_set0_key() function
  3. unsigned char exp_arr[] = {0x01, 0x00, 0x01};
Chinaman answered 21/7, 2021 at 7:42 Comment(2)
I am not really an expert, but a quick search about this comes up with a different function used to generate RSA Key pairs from data, such as RSA_Generate_Key. Maybe this post could help?Whorled
RSA_Generate_Key is deprecated in OSSL 3.0 (as it is low-level), the function I'm using is pointed to by the official migration guide.Percyperdido
C
6

It is not obvious in the manual (nothing new with OpenSSL).

The problem is that the OSSL_PARAM params array cannot be initialized the way it is in the code above. It needs to be built using OSSL_PARAM_BLD, like this:

    OSSL_PARAM_BLD *params_build = OSSL_PARAM_BLD_new();
    if ( params_build == NULL ) {
        goto OPENSSL_ERROR;
    }
    if ( !OSSL_PARAM_BLD_push_BN(params_build, "n", modulus) ) {
        ERROR("Error: failed to push modulus into param build.\n");
        goto OPENSSL_ERROR;
    }
    if ( !OSSL_PARAM_BLD_push_BN(params_build, "e", exponent) ) {
        ERROR("Error: failed to push exponent into param build.\n");
        goto OPENSSL_ERROR;
    }
    if ( !OSSL_PARAM_BLD_push_BN(params_build, "d", NULL) ) {
        ERROR("Error: failed to push NULL into param build.\n");
        goto OPENSSL_ERROR;
    }
    OSSL_PARAM *params = OSSL_PARAM_BLD_to_param(params_build);
    if ( params == NULL ) {
        ERROR("Error: failed to construct params from build.\n");
        goto OPENSSL_ERROR;
    }

It'll probably work the same with all other types of keys created with EVP_PKEY_fromdata() function.

[IMPORTANT!] Remember to check what are settable parameters for the key you're trying to create, otherwise you might get stuck on that part for a long time not knowing what's wrong with your code ;)

Chinaman answered 21/7, 2021 at 10:52 Comment(2)
Thanks for sharing this. Looks like it would be good idea to stay with deprecated functions for a while...Flocculate
It is 2023 and it is most important information on the internet regarding OpenSSL usage. Thank you Pawel.Courland

© 2022 - 2024 — McMap. All rights reserved.