RSA PKCS 15 signature generation/verification failure

Hi,

I’m trying to perform signature generation for RSA PKCS 15 mode.
Here is my call:

rc = mbedtls_rsa_rsassa_pkcs1_v15_sign( &rsa_ctx, mbedtls_ctr_drbg_random, &ctr_drbg, MBEDTLS_RSA_PRIVATE, MBEDTLS_MD_SHA256,
                                                32, hash_result, signature );

The rc value is always != 0. But I don’t see what’s wrong with the parameters I’m passing into the call.

I’ve checked the value of hash_result and it does have correct hashvalue for the message (generated using
mbedtls_md).
rsa_ctx has got all my values that I’ve passed in (P,Q,N,D,E). After I imported values into rsa_ctx, I checked the return value of mbedtls_rsa_complete() and it is 0 (successful).
signature is where my signature is stored.
ctr_drbg snippet is shown below:

 mbedtls_ctr_drbg_context ctr_drbg;
 mbedtls_entropy_context entropy;
 const char *pers = "rsa key generation";

 mbedtls_ctr_drbg_init( &ctr_drbg );
 mbedtls_entropy_init( &entropy );

 mbedtls_ctr_drbg_seed( &ctr_drbg, mbedtls_entropy_func,
                        &entropy, (const unsigned char *) pers,
                        strlen( pers ) );

Tried to verify too:

 rc = mbedtls_rsa_rsassa_pkcs1_v15_verify(&rsa_ctx, NULL, NULL, MBEDTLS_RSA_PUBLIC, MBEDTLS_MD_SHA256,
                                                     32, hash_result, signature );

This also returns non zero value.

Can anyone please suggest me what’s wrong with my call?

Note: I also tried mbedtls_rsa_rsaes_pkcs1_v15_encrypt() for signature gen and didn’t succeed.

Hi @athorath
Have you checked what the value of you error code?
Sometimes the value explains the reason for failure.
Please provide more information, as the error code, and complete flow.
regards,
Mbed TLS Team member
Ron

@roneld01: Firstly, thank you so much for responding to my question.
I’ve printed the return code from verify function and it is
“mbedtls_rsa_rsassa_pkcs1_v15_verify = -17280”.

I had captured the return codes of all mbedtls APIs up to the point of calling the verify function and all functions until that point returned 0 which is why I don’t suspect other calls to be contributing to the verify error I’m seeing.

All the values that are passed into the function like N, E, I’ve made sure they are correctly copied into rsa context and printed them out and they look good!

I’ve just pasted the entire verification function I’m developing below for reference:

unsigned char hash_result[1000];
int msg_len;
mbedtls_rsa_context rsa_ctx;
mbedtls_mpi N, E;
int rc = -1;

memset( hash_result, 0x00, 1000 );
mbedtls_mpi_init( &N ); mbedtls_mpi_init( &E );
mbedtls_rsa_init ( &rsa_ctx, MBEDTLS_RSA_PKCS_V15, 0 );

mbedtls_mpi_read_binary(&N, N, modulus/8);
mbedtls_mpi_read_binary(&E, E, modulus/8);

rc = mbedtls_rsa_import( &rsa_ctx, &N, NULL, NULL, NULL, &E );

msg_len = strlen(message);

if( mbedtls_md_info_from_type( MBEDTLS_MD_SHA1) != NULL )
{
      rc = mbedtls_md( mbedtls_md_info_from_type( MBEDTLS_MD_SHA1),
                       message, msg_len, hash_result );
}

rc = mbedtls_rsa_rsassa_pkcs1_v15_verify(&rsa_ctx, NULL, NULL, MBEDTLS_RSA_PUBLIC, MBEDTLS_MD_SHA1,
                                         20, hash_result, signature );

Hi @athorath
I assume you have MBEDTLS_MD_SHA1 defined in your configuration.

You should call mbedtls_rsa_complete() after you importthe information.
Also, size of E is not modolus/8 so this is probably the root cause
I am confused though where you get your modolus and exponent information? You are filling N and ~E` from what binary input?

I suggest you change the value of 1000 to MBEDTLS_MD_MAX_SIZE

Regards

  1. MBEDTLS_MD_SHA1 : “md.h” is included in my file. That should handle it correct? Or do I need some extra steps?
  2. The values modulus, N and E are passed into the function from another function.
  3. Changed 1000 to MBEDTLS_MD_MAX_SIZE.
  4. I’ve added in a call to mbedtls_rsa_complete(). Checked return value from this call and it is 0. But verify after this still gives “-17280”.
  5. My modulus value is 1024 which means E will be of size modulus/8 which is 256.

Pasted snippet of my input file:

# CAVS 21.3
# "FIPS186-4 - SigVer RSA PKCS#1 Ver 1.5" information
# Combinations selected:Mod Size 1024 with SHA-1 

[mod = 1024]

n = b6b2d24e5b8ffe32385ead7fe960978f450aa35657bd52c1c30a2050946fc358cc4ccfbee2308142babd79e73952a97544cc25dda95a57469da7a460e33bfa22caee2a5105f1bc2fa7876254b305a89f56d011f8619029ccd99355f92dd92f858dd0183cd759529e6c6bbccd93669bbf02aa983d9c25dffae5baa5c471fe82ef

SHAAlg = SHA1
e = 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010001
Msg = c36e9cb10117b370f5e3953d7ccc9f0e7dad93ad6eb23ec51a0c583da1e9abc6c0a378b05237160217fadcc9b58741b0fcfc42d16e6604cbff79bb151985ca92e3a52c65c33a12062297cd956ffeef6f66ccad0092f088d810a12d009751998eb5dc80775b06f0a59c243249b219f17342849de0e1381212d6ed75a621355fe3
S = 551266e8ae0df751d39ae78664f79c60f75176278abea0b0cf8e6eaa1f73bd8413dc60c6065f45cb121c10833c7516d9fbff96f7ef68b8a19ae09dd4dafebd655efb71ae6552336ec079b2fefea0f15ea76a9fb8eda8376e4fdfbabf0c3008be174bf284b7824214f64376781bb56d5f86576d3aa2604c83b204a7169487c38c

Hi @athorath

  1. MBEDTLS_MD_SHA1 : “md.h” is included in my file. That should handle it correct? Or do I need some extra steps?

No, you should verify that MBEDTLS_MD)SHA1 is configured in your configuration file. See How to configure Mbed TLS — Mbed TLS documentation for more information.

As you can see from yourinput, E is not really 256 bytes. however since it includes the leading 0, perhaps it generates your mbedtls_mpi E correct.
However, I would recomend you use the actual value of your input buffer, it could also be an endianity issue.
Regards

Thanks for the tip regarding the configuration. I’ll try that out.
And I made a typo while talking about size of E. It should be modulus/8 which is 1024/8 and that’s 128 which is what I’m using for E (and N).

Thanks for being so patient with me!
Please pardon me if this is a stupid question. What is the purpose of this config.h file? I know it says it is to perform some platform specific settings. But if I include md.h, MBEDTLS_MD_SHA1 should be included isn’t it, as this is not a platform specific thing?

I tried out a few things and I’ve listed the steps below:

  1. I ran the confil.pl script to set MBEDTLS_MD_SHA1 .

    $ ~/mbedtls-2.9.0-apache/mbedtls-2.9.0/scripts/config.pl -f /home/amritha/mbedtls-2.9.0-apache/mbedtls-2.9.0/include/mbedtls/config.h set MBEDTLS_MD_SHA1
    A #define for the symbol MBEDTLS_MD_SHA1 was not found in /home/amritha/mbedtls-2.9.0-apache/mbedtls-2.9.0/include/mbedtls/config.h

  2. Because the message said MBEDTLS_MD_SHA1 isn’t already present in config.h, I ran the same script with -o (force) option.

$ ~/mbedtls-2.9.0-apache/mbedtls-2.9.0/scripts/config.pl -o -f /home/amritha/mbedtls-2.9.0-apache/mbedtls-2.9.0/include/mbedtls/config.h set MBEDTLS_MD_SHA1 4

  1. After the previous step, the end of config.h file looks like this:

    #endif /* MBEDTLS_CONFIG_H */
    #define MBEDTLS_MD_SHA1 4

  2. Now when I try to build my code, I see the following error:

    /home/amritha/mbedtls-2.9.0-apache/mbedtls-2.9.0/include/mbedtls/config.h:2880:25: error: expected identifier before numeric constant
    #define MBEDTLS_MD_SHA1 4
    ^
    /home/amritha/mbedtls-2.9.0-apache/mbedtls-2.9.0/include/mbedtls/md.h:61:5: note: in expansion of macro ‘MBEDTLS_MD_SHA1’
    MBEDTLS_MD_SHA1, /**< The SHA-1 message digest. */

I’m guessing that’s because I’m trying to define a variable that’s already defined.
Have I made any mistakes in using the config.pl to set MBEDTLS_MD_SHA1?

Hi @athorath
Mbed TLS is a highly configurable library, which you can compile only the features you need. To configure it, you need to follow th guidelines in the link I showed you earlier. I also suggest you read https://tls.mbed.org/kb/how-to/mbedtls-tutorialhttps://tls.mbed.org/kb/how-to/mbedtls-tutorial. The configuration file is used to set platform specific settings, but also to opt out \ in specific modules and features.

But if I include md.h, MBEDTLS_MD_SHA1 should be included isn’t it, as this is not a platform specific thing?

i apologize for the type earlier. MBEDTLS_MD_SHA1 is an enum defined in md.h, but the SHA1 feature is defined in the configuration file as MBEDTLS_SHA1_C. Please verify that this is defined in your configuration file. Again, I apologize for the typo.

As for your E size value, its value should be 3 bytes (010001), however since you are setting the full E, with the leading zero bytes, it may not affect.
Regards

@roneld01 : I checked the config.h file and see #define MBEDTLS_SHA1_C.
The error code 17280 translates to 0x4380 and the error description is "The PKCS#1 verification failed". All calls until the point of pkcs verify call return a 0 which is why I’m not sure what could be causing it.

Note: I had a similar problem with ECDSA signature verification and all calls leading upto verify were 0. So I’m not sure what’s the issue. If I figure it out for one, I can solve the other one too.

@athorath yes, the error you are receiving is verification failure, however if you didn’t have MBEDTLS_SHA1_C defined, it meant that you didn’t digest the message, and actually doing verification on garbage hash_result.
The error you are receiving could be caused by several reasons, most likely is that one of your input parameters is wrong, however it could be endianity issue or memory issue as well. I would suggest you look at all the input parameters: key, signature, hash etc…
What key were you using to sign the message and generate the signature?

I did have the MBEDTLS_SHA1_C defined in config.h and hence that’s not an issue.
And checked the hash value and it looks correct.
I’ll check the input parameters.
And regarding the key for sig generation, I’m using the NIST’s request file for signature verification. So this is not a case where I generate signature and then verify.
The signature is already provided in input file and I just verify it. Input file snippet shown below:

[mod = 1024]

n = b6b2d24e5b8ffe32385ead7fe960978f450aa35657bd52c1c30a2050946fc358cc4ccfbee2308142babd79e73952a97544cc25dda95a57469da7a460e33bfa22caee2a5105f1bc2fa7876254b305a89f56d011f8619029ccd99355f92dd92f858dd0183cd759529e6c6bbccd93669bbf02aa983d9c25dffae5baa5c471fe82ef

SHAAlg = SHA1
e = 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010001
Msg = c36e9cb10117b370f5e3953d7ccc9f0e7dad93ad6eb23ec51a0c583da1e9abc6c0a378b05237160217fadcc9b58741b0fcfc42d16e6604cbff79bb151985ca92e3a52c65c33a12062297cd956ffeef6f66ccad0092f088d810a12d009751998eb5dc80775b06f0a59c243249b219f17342849de0e1381212d6ed75a621355fe3
S = 551266e8ae0df751d39ae78664f79c60f75176278abea0b0cf8e6eaa1f73bd8413dc60c6065f45cb121c10833c7516d9fbff96f7ef68b8a19ae09dd4dafebd655efb71ae6552336ec079b2fefea0f15ea76a9fb8eda8376e4fdfbabf0c3008be174bf284b7824214f64376781bb56d5f86576d3aa2604c83b204a7169487c38c

I “may” have figured out what could be causing this issue (not sure though!).
I printed all the inputs to verify function (shown below):

N : B6B2D24E5B8FFE32385EAD7FE960978F450AA35657BD52C1C30A2050946FC358CC4CCFBEE2308142BABD79E73952A97544CC25DDA95A57469DA7A460E33BFA22CAEE2A5105F1BC2FA7876254B305A89F56D011F8619029CCD99355F92DD92F858DD0183CD759529E6C6BBCCD93669BBF02AA983D9C25DFFAE5BAA5C471FE82EF

E : 010001

SHA type : SHA1

Message is c36e9cb10117b370f5e3953d7ccc9f0e7dad93ad6eb23ec51a0c583da1e9abc6c0a378b05237160217fadcc9b58741b0fcfc42d16e6604cbff79bb151985ca92e3a52c65c33a12062297cd956ffeef6f66ccad0092f088d810a12d009751998eb5dc80775b06f0a59c243249b219f17342849de0e1381212d6ed75a621355fe3

md_type is 4

Hash length in bytes is : 20

Hash result : 354db92e2152200d931186d448d3642a837c8c1d

Signature value : 551266e8ae0df751d39ae78664f79c60f75176278abea0b0cf8e6eaa1f73bd8413dc60c6065f45cb121c10833c7516d9fbff96f7ef68b8a19ae09dd4dafebd655efb71ae6552336ec079b2fefea0f15ea76a9fb8eda8376e4fdfbabf0c3008be174bf284b7824214f64376781bb56d5f86576d3aa2604c83b204a7169487c38c

All values look good except for “Hash result”. When I hash the “message” online, the hash value expected is “fdc4732ac985d3d8935b846b66d49d4190cc6197” but I’ve got “354db92e2152200d931186d448d3642a837c8c1d”.

So I used the sample code from rsa test suite to see what calls are different from my code and here is the screenshot. (Green underline means present only in test suite, blue means present only in my code).

“message” and “signature” are passed into my function (of type unsigned char *).
Hash value is calculated using mbedtls_md(). Is there anything wrong with my code?
I’ve skipped the unhexify() calls given in test suite code as it converts the string into unsigned char * but my input is already in that format. I’ve tried it with unhexify calls and still no use!
#define MBEDTLS_SHA1_C is present in config.h.

THANKS A LOT FOR YOUR SUPPORT!

HI @athorath
I tried to calaulate the digest from your message, and I got same result as you.
Note that the result you got in an online digest tool is when you send the message as a 256 byte long string, not a 128 byte long binary buffer.

This could hint for the cause of the failures. You should check the inpout data and how you treat it. Usually it’s not a string, so you shouldn’t use string functions ( e.g. strlen(), strcpy()` etc… )
Regards