2

I try to load a public RSA key to my program. I use openssl lib in C. The key is defined in header crypt.h file:

#define PUBLIC_KEY  "-----BEGIN PUBLIC KEY-----\n" \
                    "MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAuDcT2OiToi9edqil/3ha\n" \
                    "1MMrgqYvdYObRkb8C5SZtf8iv4LynuHi3hvEtybqFW84Uf2l3Dxuz3IWVp2v1C2f\n" \
                    "cUxwf+hFqL4Nt2Ww/XOKLtFXTSX/2fPYoelmLja2grHPSuFx6N4gtDUXRIGSYXIz\n" \
                    "c2GBx8lOiOP+qUguFmWZ9E0GiMLvh4XUQUzTGr4ZNNoc5LODdO0g7beFFqhntt9w\n" \
                    "EKdceGQtA7Zyt5l13x0lj+RONdPJkDFZrNGdqDwNUSog9mufpvR1P2UW09pC+lzy\n" \
                    "z32P+w0U3Za4zv4Btis9ky16vaqdN/KlDWJRt+4W9TQSAL0x9w708OQr0Sf2CXNq\n" \
                    "EobSLZ/aybe75yQmzFqmn10X+NuwTtJkArIKK7JONCBSxjohQmTZw0U497TCEHia\n" \
                    "itzgsHNLf1of31G/3GK5rCkm9fl39nnrg0yJi1cONTDjSHzKlrPhA584jFRD0CIO\n" \
                    "VNHYgsVLuFQuJ0WkZON8uEZELXN1ZyWnmPXH8wSwxjud65JD4JSQornCXorBMfxd\n" \
                    "DFEeeNk8tjgPMaCTLFNP/gfVDzkvcct9RoC8uZxHk8zgrGOwuxOZ/ZyihE7M8v0i\n" \
                    "+VwG9iMrPl8W3+KqunIt/FB4Le1vJ0yYorK64DRNdeMAIsYq2iFWO3GXNsX631/K\n" \
                    "EuZJS8tGNhK9dF5umo0GceUCAwEAAQ==\n" \
                    "-----END PUBLIC KEY-----\n"

The RSA key is supposed to be saved in RSA * structure. I use a global variable for that.

RSA *rsaPubkey;

The main() calls a function that will take PUBLIC_KEY and pass it to rsaPubkey. The function is shown bellow:

#include "crypt.h"

int EVP_PKEY_get_type(EVP_PKEY *pkey) {
    if (!pkey)
        return EVP_PKEY_NONE;

    return EVP_PKEY_type(pkey->type);
}

int PublicRSAKeyToStruct(const char *pubKey) {
    BIO* bio;
    bio = BIO_new_mem_buf(pubKey, (int)sizeof(pubKey));
    if (bio == NULL) {
        printf("bio");
        return -1;
    }

    EVP_PKEY* pkey;
    PEM_read_bio_PUBKEY(bio, &pkey, NULL, NULL);
    if (pkey == NULL) {
        printf("pkey");
        return -1;
    }

    int type = EVP_PKEY_get_type(pkey);
    if (type != EVP_PKEY_RSA && type != EVP_PKEY_RSA2) {
        printf("get type");
        return -1;
    }

    rsaPubkey = EVP_PKEY_get1_RSA(pkey);
    if (rsaPubkey == NULL) {
        printf("pubkey");
        return -1;
    }

    EVP_PKEY_free(pkey);
    BIO_free(bio);
    return 0;
}

We call the function like that:

status = PublicRSAKeyToStruct(PUBLIC_KEY);
if (status == -1) {
    exit(EXIT_FAILURE);
}

My problem is that the PublicRSAKeyToStruct() function throws me the bellow user defined error:

get type

This means that we failed to pass EVP_PKEY_get_type(). I can't understand why this happen though. I have also no clue if the problem is on the previous steps.

4
  • 1
    What is the value of type when the error occurs? Commented Jan 14, 2017 at 17:32
  • @Alden it's zero (0). So there is a failure somewhere? Commented Jan 14, 2017 at 18:19
  • @GuyL: don't do that. The data shown IS in PUBKEY=SPKI format and is NOT in RSA PUBLIC KEY (raw PKCS1) format. Commented Jan 14, 2017 at 20:32
  • @dave_thompson_085 - You're right. Commented Jan 14, 2017 at 20:33

1 Answer 1

1

Your PEM_read call failed because the BIO you gave it doesn't access the correct data, but you didn't check the return value, and you didn't initialize pkey so even though it's not valid your pkey == NULL check doesn't catch it. As described in the man page on your system (unless Windows) or on the web the second argument to BIO_new_mem_buf must either be the number of bytes in the buffer or -1 if buffer contains a null-terminated C string -- and a string literal like yours does yield a null-terminated string so -1 is suitable -- but sizeof(apointer) is neither of these.

The remainder of your code is correct and works fine if you give it a valid EVP_PKEY*.

Sign up to request clarification or add additional context in comments.

2 Comments

I chagned it to bio = BIO_new_mem_buf(pubKey, -1);. Now it works. Please add it in your answer. Also add the reference to linux.die.net/man/3/bio_new_mem_buf that suggest to add -1 in second parameter. Change this so the others can understand it. Either way I'll accept your answer. (please add those infos).
@GeorgeGkas: I prefer not to reference linux.die.net for things that vary from version to version and OpenSSL does vary in many areas though not AFAIR for memBIO, so I used my preferred style instead. Yes, if you have a private key in one of the several PEM formats OpenSSL uses, PEM_read_bio_PrivateKey will read it. Note that (unlike publickeys) privatekeys are often password-encrypted, and if so your call should provide either the password itself or a callback that gets the password.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.