Hi Jacob,

Thanks for the reply. I'm back on the project again - sorry that I didn't respond sooner.

I have to parse keys that are stored in a particular format, over which I likely have no control. For my initial proof-of-concept that's what I was able to do.

I'll definitely look into the WOLFSSL_PUBLIC_MP define, which might end up cleaning my interface up a bit. Thanks!

Jacob,

Thank you. That solves the issue.

I'm running WolfSSL 3.12 compiled with keygen and fortress. Harden is disabled.

I am getting BAD_STATE_E (-192) every once in a while. I've never seen this when using the same code in 3.9.6. The sample code is:

#include "wolfssl/options.h"
#include "wolfssl/wolfcrypt/rsa.h"
#include "wolfssl/wolfcrypt/asn.h"
#include "wolfssl/wolfcrypt/aes.h"
#include "wolfssl/wolfcrypt/hmac.h"
#include "wolfssl/wolfcrypt/integer.h"

...

int rval;
RsaKey rsaKey;
rval = wc_RsaPublicKeyDecodeRaw(n, nLen, e, eLen, &rsaKey);
if (rval < 0) printf(...);

rval = wc_RsaSSL_Verify(pIn, inLen, pOut, outLen, &rsaKey);
if (rval < 0) printf(...);

The wc_RsaSSL_Verify call seems to fail about 50% of the time.

I've added the line (rsaKey.data = NULL) between the two wc_* functions which hasn't helped.
I added rsaKey.state = 0 in between the two functions, which seems to make the routine work 100% of the time.
I've seen the state variable be 32767, 32765, and 0.

Is there some other way I'm supposed to initialize the rsaKey variable? Is there maybe a configuration issue? It seems like the state isn't getting modified in the PublicKeyDecodeRaw function at all.

As a follow up, I got everything working by manually parsing the parameters into p, q, dP, dQ, u, n, and e. Private key decryption works as expected. The code posted above would have been nice to be able to use, but I didn't want to try to fight the linker.

Is there a way to manually populate the parameters of an RSA private key? I had come up with this, but get linker errors of "undefined reference to mp_init and mp_read_unsigned_bin"

int parseMPIntFromBuffer(mp_int* mpi, const uint8_t *pIn, int length)
{
    if (mp_init(mpi) != MP_OKAY)
    {
        printf("Error initializing MP integer\n");
        return -1;
    }

    if (mp_read_unsigned_bin(mpi, pIn, length) < 0)
    {
        printf("Error reading bignum\n");
        return -1;
    }
    return 0;
}

...

    // Parse the key values
    if (
               (parseMPIntFromBuffer(&(pKey->p),  &(pIn[0 * 64]), 64) != 0)
            || (parseMPIntFromBuffer(&(pKey->q),  &(pIn[1 * 64]), 64) != 0)
            || (parseMPIntFromBuffer(&(pKey->dP), &(pIn[2 * 64]), 64) != 0)
            || (parseMPIntFromBuffer(&(pKey->dQ), &(pIn[3 * 64]), 64) != 0)
            || (parseMPIntFromBuffer(&(pKey->u),  &(pIn[4 * 64]), 64) != 0)
       )
    {
        printf("Error parsing the private key\n");
        return -1;
    }

If there isn't a way to expose those functions to the linker, is it guaranteed across architectures that the buffer will be entirely little-endian? If so, I should be able to populate the "used, alloc, sign" elements of mp_int and simply reverse the buffers to get the private key - though that seems like it would be reinventing the wheel.

Thanks in advance.

6

(7 replies, posted in wolfCrypt)

I'm having an issue reading in Der files to an RSA key as well, though my issue is slightly different.

I'm saving the der to a file with the following code (error checks omitted):

int saveKeypair(char *sPubkeyFile, char *sPrivkeyFile, RsaKey *pRsaKey)
{
    FILE *pubkeyFile = fopen(sPubkeyFile, "w");
    uint8_t data[4096];
    int dataSize = wc_RsaKeyToDer(pRsaKey, data, sizeof(data));

    int retval = fwrite( data, dataSize, 1, pubkeyFile);

    fclose(pubkeyFile);

    return 0;
}

Everything seems to work fine, because I can successfully read everything back using

int tryOpenKeypair(char *sPubkeyFile)
{
    FILE *pubkeyFile = fopen(sPubkeyFile, "r");
    uint8_t data[4096];

    int dataSize = fread(data, 1, sizeof(data), pubkeyFile);
    
    fclose(pubkeyFile);

    RsaKey *pTempRsaKey = malloc(sizeof(RsaKey));
    wc_InitRng(&rng);
    wc_InitRsaKey(pTempRsaKey, 0);

    unsigned int idx = 0; // Start of the data...
    int retval = wc_RsaPublicKeyDecode(data, &idx, pTempRsaKey, dataSize);
    
    uint8_t new_e[3];
    uint8_t new_n[384];
    uint32_t new_e_size = 3;
    uint32_t new_n_size = 384;
    int ret = wc_RsaFlattenPublicKey(pTempRsaKey, new_e, &new_e_size, new_n, &new_n_size);

    if (ret != 0)
    {
        printf("Error flattening public key: %d\n", ret);
        printf("pubkey buffer size = %d\n", pubkey_buffer_size);
        return -1;
    }
    else
    {
      printf("Successfully flattened key\n");
      printf("New N %d ", new_n_size);
      print_buffer(new_n, new_n_size);
      printf("New E %d ", new_e_size);
      print_buffer(new_e, new_e_size);
    }
}

The results that I get are

Successfully flattened key
New N 0 Buffer:
New E 128 Buffer:
        0xc8 0xc9 0xcb 0xed 0xcc 0xc0 0x3c 0xcf
        0xc7 0x92 0x73 0x6f 0x76 0x38 0x1d 0x9a
        0xf7 0x08 0x2f 0x43 0x80 0x00 0x00 0x00
        ...

The exponent buffer is clearly corrupting memory during the flatten operation. Before writing the key, I verify that my syntax is right:

    int ret = wc_MakeRsaKey(pRsaKey, numBytes * 8, 65537, pRng);

    // Try to get the key now
    unsigned int new_e_size, new_n_size;
    new_e_size = 3;
    new_n_size = numBytes;
    ret = wc_RsaFlattenPublicKey(pRsaKey, pPubkey_e, &new_e_size, pPubkey_n, &new_n_size);

    if (ret != 0)
    {
        printf("Error flattening public key: %d\n", ret);
        return -1;
    }
    else
    {
        printf("New E Buffer %d \n", new_e_size);
        print_buffer(pPubkey_e, new_e_size);
        printf("New N Buffer %d \n", new_n_size);
        print_buffer(pPubkey_n, new_n_size);
        *pPrivkey = (void *)pRsaKey;
    }

    saveKeypair(pPubFileName, pPrivFileName, pRsaKey);
    return 0;

This leads to a successful print statement, that I would expect

Successfully created the RSA key               
New E Buffer 3                                 
Buffer:                                       
        0x01 0x00 0x01                         
New N Buffer 128                               
Buffer:                                       
        0xc3 0x55 0x51 0x0d 0x8d 0xa2 0x6a 0xad
        0x61 0xb6 0xdb 0xe0 0x8e 0x02 0x6e 0xf7...

Is there maybe an issue with having multiple RsaKey's malloc'd at the same time? Perhaps there is an initialization that I need to perform before I can decode the key. I seem to have the same issue when running from an openssl generated keypair as well.

Lastly, there doesn't seem to be a way to encode a private key to a DER or PEM format. There seems to be a way to decode them. Is there a way that the private keys can be saved for future access as well?

Thanks for the help!



EDIT: This seems to work when N is 384 bytes, but not when N is 128 bytes. Also, it only seems to work when I have created a key using openssl and NOT when I write the key as above.

Successfully flattened key                     
New N 384 Buffer:                               
        0xb2 0x3f 0x07 0x0c 0x20 0x24 0x00 0x39
        0xe7 0x04 0xa8 0x95 0x3e 0x63 0x10 0xec
        ...
New E 3 Buffer:
        0x01 0x00 0x01

Code to generate 384 byte key was taken from this website, substituting DER for PEM:
https://rietta.com/blog/2012/01/27/open … m-command/

7

(3 replies, posted in wolfCrypt)

Hi Chris,

Thanks! It seems like I was missing the options.h include that you mentioned. I realize now that I neglected to cite my includes from above.

Adding those lines seems to have fixed the problem.

8

(3 replies, posted in wolfCrypt)

I'm trying to create an RSA keypair using the following code:

int main()
{
    RsaKey rsakey;
    printf("Memory allocated\n");

    RNG rng;
    wc_InitRng(&rng);
    printf("Ring initialized\n");
    wc_InitRsaKey(&rsakey, 0);
    printf("RSA key initialized\n");

    int ret = wc_MakeRsaKey(&rsakey, 1024, 65537, &rng);

    printf("RSA key made\n");

    if (ret != 0)
        printf("Error creating RSA key\n");
    else
        printf("Successfully created the RSA key\n");

    return 0;
}

I have even placed the return 0 after the wc_MakeRsaKey line. When I run this program, I see the following output:

$ ./main
Memory allocated
Ring initialized
RSA key initialized
RSA key made
Successfully created the RSA key
*** stack smashing detected ***: <unknown> terminated
Aborted (core dumped)

I have tried including the wolfssl/wolfcrypt/rsa.h as well as the cyassl/ctaocrypt/rsa.h files, both seem to have the same problem.

I have downloaded the wolfssl3.9.6 file, configured it with

./configure --enable-keygen

, I can verify the install with

wolfssl-config --version

The code is compiled with the following Makefile (excerpt)

CC=gcc
CFLAGS=-c -Wall -I/usr/local/lib

all: main

main: main.o
    $(CC) main.o -o main -lwolfssl

main.o: main.c
    $(CC) $(CFLAGS) main.c

Is there a step that I am missing? Why does this seem to always lead to stack smashing / seg faults?

Thanks for the help!