1

I have to sign an array of data using SHA1 with RSA signature, with my private key in C. I am using OpenSSl libraries. However i always get no OPENSSL_Applink error. I have tried following:

  • include applink.c
  • static link libraires only libcrypto-1_1.a
  • debug applink.c to see the problem with the table
  • since i coundn't include applink.c i manually added the source code in the same filename in my project, which resulted in a non-responsive application.

I am using eclipseCDT oxygen version. I am a begginer in openSSl libraries and also would like if someone knows a good example of doing it to send me the link. I also tried adding OpenSSL_add_all_digests(), and OpenSSL_add_all_algorithms(), with no success.

Note: The code here may be wrong, but my problem is when compiler hits first custom function of openssl library project crashes with error no OPENSSL_Applink, so that's my main problem, not fixing the code itself.

Here is a code snippet:

int rsaSign(char *in_file, char * sig_file){

    char *data = NULL;
    int data_len;
    unsigned int sig_len;
    unsigned char *sig;
    int err = -1;

    OpenSSL_add_all_digests();
    FILE *fd;
    EVP_PKEY *priv_key = EVP_PKEY_new();
    RSA *privkey = NULL;
       printf( "we are here..\n");

    if ((fd = fopen(PRIVKEY_FILE, "r")) == NULL){
        printf("error reading file\n");
        exit(0);
    }

    privkey = RSA_new();
    if (!PEM_read_PrivateKey(fd, &privkey, NULL, NULL))
    {
        fprintf(stderr, "Error loading RSA Private Key File.\n");
        return 2;
    }

    fclose(fd);

    if (!EVP_PKEY_assign_RSA (priv_key, privkey))
    {
        fprintf(stderr, "EVP_PKEY_assign_RSA: failed.\n");
        return 3;
    }

    if (!priv_key) {
        printf("no private key\n");
    }
    EVP_PKEY_set1_RSA(privkey, priv_key);


    EVP_MD_CTX *ctx = EVP_MD_CTX_create();

    const EVP_MD *md = EVP_get_digestbyname("SHA1");

    if (!md) {
        fprintf(stderr, "Error creating message digest");
        fprintf(stderr, " object, unknown name?\n");
        ERR_print_errors_fp(stderr);
        exit(1);
    }



    if (!EVP_SignInit(ctx, md))
        {
            fprintf(stderr, "EVP_SignInit: failed.\n");
            EVP_PKEY_free(priv_key);
            return 3;
        }
    printf( "now to sign update..\n");
    data = readFile(in_file);
    data_len = strlen(data);
    printf("data len = %d\n", data_len);

    if (!EVP_SignUpdate(ctx, data, data_len))
    {
        fprintf(stderr, "EVP_SignUpdate: failed.\n");
        EVP_PKEY_free(priv_key);
        return 3;
    }
    printf( "now to sign final..\n");

    sig = malloc(EVP_PKEY_size(privkey)); //!!!!! SEGMENTATION FAULT HERE !!!!!


    if (!EVP_SignFinal(ctx, &sig, &sig_len, priv_key))
    {
        fprintf(stderr, "EVP_SignFinal: failed.\n");
        free(sig);
        EVP_PKEY_free(priv_key);
        return 3;
    }

    free(data);
    free(sig);
    EVP_PKEY_free(priv_key);
    return EXIT_SUCCESS;

    }
jww
  • 97,681
  • 90
  • 411
  • 885
  • You say you cannot link to `libssl` (e.g. link with `-lssl -lcrypto`)? – David C. Rankin May 15 '17 at 17:22
  • I can link them, or any other, but my goal is to static link them, since i read there is a problem if you use dll with my case(no OPENSSL_Applink) – Ljubomir Maksimovic May 15 '17 at 17:27
  • Maybe i forgot to mention, my program is single threaded , and when i was debugging i noticed that it uses multithreads, so could that be a problem? – Ljubomir Maksimovic May 15 '17 at 17:36
  • Well, that is generally only a problem if you want to distribute your code. Eclipse should have no problem setting up the correct environment to find the .dll libraries (which tells me you are on windoze). This is where there are a number of differences depending on whether you are using VS or MinGW (there are differences in versions of MinGW as well). You may want to look at [**how to do static linking of libwinpthread-1.dll in mingw?**](http://stackoverflow.com/questions/13768515/how-to-do-static-linking-of-libwinpthread-1-dll-in-mingw) for guidance. – David C. Rankin May 15 '17 at 17:40
  • Thanks, yea, i use windoze, minGW 3.4.5 version, and yeah, i want to distribute code. Do you think the problem could be that i am using precompiled version of openssl? – Ljubomir Maksimovic May 15 '17 at 17:46
  • Yes, a statically compiled openssl library will do. There are two versions of MinGW -- you want the one that is distributed along with Code::Blocks (it is the TD.. version, the WD.. version has additional dll dependencies that are difficult to work around) I have googled it a couple of times, but don't use windoze, so I'm not the best person to ask. I know there are probably 50+ questions (with good answers) here on SO. – David C. Rankin May 15 '17 at 18:01

1 Answers1

1

Your code passes &privkey which is type RSA** to PEM_read_PrivateKey which requires (per its prototype) EVP_PKEY**; your compiler should have diagnosed this. Similarly EVP_PKEY_size requires EVP_PKEY* not RSA*. With the generic read, you don't need any RSA* at all and need not and must not use EVP_PKEY_assign_RSA.

Applink should work if your code (including all calls to OpenSSL AND the #include "applink.c") is in the EXE not in a DLL -- is it?

However, you can eliminate the need for Applink even with dynamic linking by avoiding APIs that use FILE* and using the BIO* forms. Thus instead of:

FILE* f = fopen (file,"r");
if( f==NULL ) ...error... 
... PEM_read_PrivateKey (f, &evpkey, NULL, NULL) ...
fclose(f);

use:

BIO* b = BIO_new_file (file,"r");
if( b==NULL ) ...error...
... PEM_read_bio_PrivateKey (b, &evpkey, NULL, NULL) ...
BIO_close(b);

or possible but clunkier:

FILE* f = fopen (file,"r"); if( f==NULL ) ...error...;
char* buf = ...read all data from f into allocated memory...;
int len = ...length of data in buf...;
fclose (f);
BIO* b = BIO_new_mem_buf (buf,len);
... PEM_read_bio_PrivateKey (b, &evpkey, NULL, NULL) ...
... free buf as appropriate ...

PS: I don't know if the MinGW package has man pages, but most Windows packages (other than Cygwin and now WSL) don't. If not you should probably bookmark and use the appropriate directory(ies) under https://www.openssl.org/docs/manpages.html .

dave_thompson_085
  • 34,712
  • 6
  • 50
  • 70