Topic: RSA encryption

The API int wc_RsaPublicEncrypt(
    const byte * in,
    word32 inLen,
    byte * out,
    word32 outLen,
    RsaKey * key,
    WC_RNG * rng
)
works if the [in] buffer length is less than 245 bytes, but I have to encrypt a buffer of 256 bytes.
In this case the API ret is RSA_BUFFER_E (-131).
How I can use the API without any padding?

Share

Re: RSA encryption

Hi Alessandro,

I assume your key size is 2048-bit. The RsaPublicEncrypt uses PKCSV15, so the max input is not the key size. To public encrypt an already padded 256-byte you would want to use `wc_RsaDirect`.

/* Function that does the RSA operation directly with no padding.
 *
 * in       buffer to do operation on
 * inLen    length of input buffer
 * out      buffer to hold results
 * outSz    gets set to size of result buffer. Should be passed in as length
 *          of out buffer. If the pointer "out" is null then outSz gets set to
 *          the expected buffer size needed and LENGTH_ONLY_E gets returned.
 * key      RSA key to use for encrypt/decrypt
 * type     if using private or public key {RSA_PUBLIC_ENCRYPT,
 *          RSA_PUBLIC_DECRYPT, RSA_PRIVATE_ENCRYPT, RSA_PRIVATE_DECRYPT}
 * rng      wolfSSL RNG to use if needed
 *
 * returns size of result on success
 */
int wc_RsaDirect(byte* in, word32 inLen, byte* out, word32* outSz,
        RsaKey* key, int type, WC_RNG* rng);

Thanks,
David Garske, wolfSSL

Share

Re: RSA encryption

thanks for the reply.
Now

ret = wc_RsaDirect(in, 30, out, 256, &key, RSA_PUBLIC_ENCRYPT, &rng);

ret is BAD_FUNC_ARG (-173)

Take in mind that using

ret = wc_RsaPublicEncrypt(in, 30, out, 256, &key)

the API works well.

I enabled the define WC_RSA_DIRECT & WC_RSA_NO_PADDING. It is enough

Share

Re: RSA encryption

Hi Alessandro,

Your input is 30 byes, which is not padded. Direct requires the input to match the key size (256 bytes).

If your input really is 30 bytes you need to apply a padding. There are a few standards like PKCSv15, PSS and OAEP.

Can you describe more about your use-case? This will help me recommend the right solution.

Thanks,
David Garske, wolfSSL

Share

Re: RSA encryption

Sorry my previous note is wrong.
I have resolved the issue

Share

Re: RSA encryption

API
int wc_RsaDirect(byte* in, word32 inLen, byte* out, word32* outSz, RsaKey* key, int type, WC_RNG* rng);
can be used also if only the public modulus and exponent are known or I must use a new API?
Thanks

Share

Re: RSA encryption

Hi Alessandro,

The RsaKey can be either a public only or private key. Depending on that you can do either a public only operation or public and private. The public modulus and exponent must be known. You would use the wc_RsaPublicKeyDecodeRaw API to import those. Example: https://github.com/wolfSSL/wolfTPM/blob … 0-L3092C34

Thanks,
David Garske, wolfSSL

Share

Re: RSA encryption

Hi,
using the API wc_RsaPublicKeyDecodeRaw the wc_RsaDirect() return the error -112.
Please see the following test code
Thanks

/********************** TEST START **************************************/
#ifdef WOLFSSL_STATIC_MEMORY
    static WOLFSSL_HEAP_HINT* HEAP_HINT;
#else
    #define HEAP_HINT NULL
#endif /* WOLFSSL_STATIC_MEMORY */

/* for async devices */
static int devId = INVALID_DEVID;

#define RSA_TEST_BYTES 256

#define MY_RSA_KEY_BITS 2048
#define MY_RSA_KEY_BYTES MY_RSA_KEY_BITS/8

static const char PKmodulus[MY_RSA_KEY_BYTES] = {
0xBD,0xCE,0x7F,0xC1,0x0D,0xC7,0x97,0xA7,0xD4,0x75,0xBB,0xAC,0x49,0x4C,0x0F,0xEC,0x20,0x16,0x29,0x99,0xC8,0xBD,0x63,0xA5,0xDB,0x7D,0xCC,0xF1,0xA6,0x6C,0x45,0xA3,
0x9D,0x65,0x6A,0xEC,0xF2,0x2D,0xA8,0xD4,0xAC,0x36,0xF5,0x2D,0x83,0xE5,0x4F,0xC6,0x78,0x0A,0x1D,0x7B,0x8F,0xAC,0x10,0xB9,0x52,0xA4,0x81,0x1C,0x73,0x64,0xF3,0xCD,
0x66,0x73,0x30,0x13,0x81,0xE3,0x91,0x46,0x3C,0x6F,0x9D,0x14,0x24,0x4B,0xDC,0xCA,0x0A,0xDC,0x9D,0xCD,0x96,0xB5,0x53,0x4B,0xD6,0xC5,0x31,0x35,0x88,0xBB,0xE3,0x2B,
0x58,0x6C,0x93,0x7B,0x9E,0xE0,0x39,0x26,0x05,0xDC,0xB5,0x8B,0x5D,0xAB,0xB5,0x8C,0x61,0x94,0x09,0x6D,0x89,0x6C,0x87,0xF6,0xB2,0xDA,0xDC,0x6B,0xED,0xB3,0xFA,0xE6,
0x42,0xBF,0x9C,0xD8,0x24,0x51,0x9C,0x21,0xCC,0x23,0x61,0xBA,0x58,0x8C,0x25,0x28,0xD5,0x10,0x28,0x96,0x3E,0x87,0x90,0xF9,0x7D,0x37,0x5C,0x00,0xEE,0x2F,0xFD,0x88,
0x9C,0x9B,0xE1,0xC4,0x79,0xD7,0x71,0xCF,0x62,0xD6,0xD4,0x21,0xE6,0x0E,0xF6,0x09,0x14,0xDB,0xCE,0xF6,0x0A,0x54,0xE6,0x41,0x4D,0x78,0x98,0x3B,0x74,0x0C,0xC9,0x70,
0xCA,0x8F,0xEA,0x26,0xF1,0x37,0x48,0xE8,0xEC,0xFF,0xDC,0xB0,0x4C,0x55,0x1B,0x86,0xCE,0x62,0xB7,0x5F,0x61,0x6D,0x8E,0x26,0x90,0x9D,0x0B,0xA3,0xB6,0xD3,0xEF,0xC3,
0x6A,0xEC,0xB9,0x39,0xAC,0x8F,0xC6,0x16,0xB8,0xBB,0x06,0xEC,0x4A,0x8C,0x9E,0xCB,0x66,0x45,0x8F,0x96,0x2C,0x91,0x70,0x2F,0xBF,0x09,0xE4,0xDE,0xBE,0x89,0xB,0x035,
};
static const char PKexponent[4] = { 0x00,0x00,0x00,0x03 };

static const char encryptedData[MY_RSA_KEY_BYTES] = {
0x20,0xB6,0x62,0x00,0x61,0x56,0x40,0xBD,0xD9,0x8E,0x23,0xAF,0x7C,0xEB,0xF4,0xE9,0x88,0x21,0x42,0x28,0x0A,0xEE,0xC3,0x23,0x39,0xF1,0x73,0x07,0xD4,0xD3,0xC3,0xDB,
0x6E,0x77,0x31,0x90,0x4B,0xBA,0x89,0x3A,0x0D,0x31,0xE2,0xEC,0x7A,0xC4,0x25,0x52,0xF8,0x48,0x98,0x6C,0xC5,0x45,0xDD,0x0A,0xD8,0x34,0x94,0x14,0xDF,0x70,0xD9,0x5F,
0xEF,0x3F,0xE5,0x58,0x67,0x45,0xC6,0x3F,0xCD,0xA6,0x58,0x31,0x3B,0x6A,0xE7,0x91,0x41,0xE5,0x93,0x40,0x05,0x69,0xA9,0x77,0xDE,0x5C,0x4D,0xDD,0xA3,0x12,0x57,0x01,
0x4A,0xFA,0x60,0x97,0xF8,0xEC,0x0F,0x97,0xF2,0xE7,0x56,0x2E,0xEB,0x0F,0xE3,0xAB,0x3A,0xC5,0x55,0xDE,0x3A,0xC6,0x47,0xF7,0xEF,0x1E,0xC5,0xB7,0x74,0x0B,0x9B,0x35,
0xAF,0x36,0xF8,0x60,0x39,0x0A,0x87,0xE7,0x6A,0xAD,0x86,0x45,0x81,0x88,0xB1,0x25,0x3A,0xF2,0xCB,0x1A,0x5E,0xF9,0x72,0x2C,0x64,0x7C,0x07,0xDA,0x54,0x5F,0xEE,0x34,
0x49,0x5F,0x2B,0xD2,0xEE,0x87,0x1C,0x80,0x19,0xC3,0xD0,0x66,0xBF,0xC5,0x79,0x51,0x18,0x57,0x0D,0x18,0x73,0x18,0x23,0x67,0x14,0x50,0x55,0x1F,0xFC,0x79,0xEE,0x88,
0xF5,0x79,0x64,0xB5,0x66,0x9D,0x43,0xA1,0xBC,0x06,0xE0,0xC2,0x6B,0x21,0x9C,0xD5,0x09,0x4B,0xD6,0xBC,0x99,0x5D,0xE4,0x22,0x45,0x02,0x9B,0x94,0xCB,0xBD,0x15,0xB8,
0x99,0xA7,0x3A,0x3B,0x67,0x6E,0x93,0xC2,0x6E,0x51,0x52,0xB1,0x23,0xD5,0x75,0x6E,0x56,0x81,0x3F,0x8A,0x42,0x8F,0xEE,0x3E,0x4E,0x39,0xDD,0x7F,0xD0,0xE2,0xA6,0xB8,
};

static char decryptedData[MY_RSA_KEY_BYTES];

int testRSA_PK_Decrypt(void)
{
  int32_t  ret = -1;
  byte     e[sizeof(word32)];
  byte     n[MY_RSA_KEY_BYTES];
  RsaKey   wolfKey;
  WC_RNG   rng;
  word32 outSz = MY_RSA_KEY_BYTES;

  memset(&wolfKey, 0, sizeof(RsaKey));
  memset(&rng, 0, sizeof(WC_RNG));
  memset(n, 0, sizeof(n));
  memset(e, 0, sizeof(e));

  /* load modulus */
  memcpy(n, PKmodulus, sizeof(PKmodulus));
  /* load exponent */
  memcpy(e, PKexponent, sizeof(PKexponent));
  outSz = sizeof(PKmodulus);

  do
  {
    /* load public key portion into wolf RsaKey */
    ret = wc_RsaPublicKeyDecodeRaw(n, sizeof(PKmodulus), e, sizeof(PKexponent), &wolfKey);
    if ( ret != 0 )
    {
      logPrintf(LOG_DEBUG, "wc_RsaPublicKeyDecodeRaw ERROR %d", ret);
      ret = -2;
      break; //stop on error
    }

    /* init Random */
    ret = wc_InitRng_ex(&rng, HEAP_HINT, devId);
    if ( ret != 0 )
    {
      logPrintf(LOG_DEBUG, "wc_InitRng_ex ERROR %d", ret);
      ret = -3;
      break; //stop on error
    }

    /* decrypt CA Public Key self-signed data with the CA Public Key */
    memset(decryptedData, 0, sizeof(decryptedData));
    do {
        ret = wc_RsaDirect((byte *)encryptedData, sizeof(encryptedData), (byte *)decryptedData, &outSz, &wolfKey, RSA_PUBLIC_DECRYPT, &rng);
    } while (ret == WC_PENDING_E);
    if ( ret <= 0 )
    {
      logPrintf(LOG_DEBUG, "wc_RsaDirect ERROR %d", ret);
      ret = -4;
      break; //stop on error
    }

    ret = 0; //OK

  } while ( 0 );

  return ret;
}
/********************** TEST END **************************************/

Share

Re: RSA encryption

Hi Alessandro,

That error typically means you have not allocated enough stack space to the task.

Can you share how you are building wolfSSL? We have a few different math library options with different memory use.

If you want to reduce stack use try with WOLFSSL_SMALL_STACK set.

Thanks,
David Garske, wolfSSL

Share

Re: RSA encryption

Hi David,
see the following setup options used to buld wolfSSl.

/****************************************** settings.h **********************************************/

/* Configuration */

#if HAL_USE_CRY
#define CRY_DRV   CRYD1
#define CRYD_KEY  0
#define HAL_CRY_WOLF_SHABUFF_SIZE 2*128
#endif

#define WOLFSSL_GENERAL_ALIGNMENT 4
#define HAVE_TM_TYPE
#define WORD64_AVAILABLE

/* ChibiOS */
#define WOLFSSL_CHIBIOS
#define WOLFSSL_CHIBIOS_HASH
#define WOLFSSL_CHIBIOS_AES
#define WOLFSSL_CHIBIOS_DES3
#define WOLFSSL_CHIBIOS_RSA
#define WOLFSSL_CHIBIOS_ECC
#define WOLFSSL_NO_HASH_RAW
/*
* alex_b 19/01/2024 to use API wc_RsaDirect() with no padding
*/
#define WC_RSA_DIRECT
#define WC_RSA_NO_PADDING
/* */

/* Lwip */
#define WOLFSSL_LWIP
#define WOLFSSL_USER_IO

/* Lwip API used with wolfssl */
#define WOLFSSL_USE_SOCKET
//#define WOLFSSL_USE_NETCONN

/* Timers */
#define USER_TICKS
#define WOLFSSL_USER_CURRTIME
#define XMALLOC_OVERRIDE
//#define USE_WOLF_TIME_T
#define XTIME(tl)       (epochTime())

//#define WOLFCRYPT_ONLY
#define HAVE_SNI

/* CMAC  */
#define WOLFSSL_CMAC

/* DEBUG  */
#define DEBUG_WOLFSSL
#define WOLFSSL_DEBUG_TLS

/* ARM  */
#define RSA_LOW_MEM
#define NO_OLD_RNGNAME
#define NO_OLD_WC_NAMES
#define SMALL_SESSION_CACHE
#define WOLFSSL_SMALL_STACK

#define TFM_ARM
#define SINGLE_THREADED
#define NO_SIG_WRAPPER

/* Cipher features */
//#define USE_FAST_MATH
//#define ALT_ECC_SIZE

//#define HAVE_FFDHE_2048
//#define HAVE_CHACHA
#define HAVE_POLY1305
#define HAVE_ECC
#define HAVE_CURVE25519
#define CURVED25519_SMALL
#define HAVE_ONE_TIME_AUTH
#define WOLFSSL_DH_CONST
#define HAVE_SUPPORTED_CURVES
#define HAVE_TLS_EXTENSIONS

#define HAVE_ECC_KEY_EXPORT
#define HAVE_ECC_KEY_IMPORT
#define HAVE_ECC_VERIFY
#define HAVE_ECC_SIGN
#define HAVE_ECC_DHE

#define WOLFSSL_DER_TO_PEM
#define WOLFSSL_PEM_TO_DER
#define WOLFSSL_HAVE_PRF
#define WOLFSSL_ENCRYPTED_KEYS

#define WOLFSSL_STATIC_RSA

/* Cipher features */
//#define HAVE_ED25519
#define HAVE_SHA384
#define HAVE_SHA512
#define WOLFSSL_AES_DIRECT
#define WOLFSSL_SHA384
#define WOLFSSL_SHA512
#define WOLFSSL_AES_COUNTER
#define HAVE_AES_CBC
#define HAVE_AESGCM

/* Size/speed config */
//#define USE_SLOW_SHA2

/* Robustness */
#define TFM_TIMING_RESISTANT
#define ECC_TIMING_RESISTANT
#define WC_RSA_BLINDING
#define WOLFSSL_KEY_GEN
#define WOLFSSL_CERT_GEN
#define WOLFSSL_CERT_REQ
#define WOLFSSL_CERT_EXT

/* File system */
#define NO_STDIO_FILESYSTEM
#define WOLFSSL_USER_FILESYSTEM

/* Remove Features */
#define NO_WOLFSSL_SERVER
#define NO_WRITEV
#define NO_DEV_RANDOM
#define WOLFSSL_NO_SOCK
#define NO_WOLFSSL_DIR
#define NO_MAIN_DRIVER
#define NO_MD4
#define NO_RABBIT
#define NO_HC128
#define NO_DSA
#define NO_PWDBASED
#define NO_PSK

/* MA_18112021 added for Retail Protocol */
#define NO_DES3

#define NO_RC4

#define WOLFSSL_AES_128
#define WOLFSSL_AES_192
#define WOLFSSL_AES_256

/* MA_08022022 added for Retail Protocol */
#define OPENSSL_EXTRA
#define OPENSSL_EXTRA_X509_SMALL
#ifndef WC_ASYNC_DEV_SIZE
    #define WC_ASYNC_DEV_SIZE 512
#endif

#if defined GBC_PCI_CERTIFICATION
  #define IGNORE_KEY_EXTENSIONS
#endif

/* Realloc (to use without USE_FAST_MATH) */
void *chHeapRealloc (void *addr, uint32_t size);
void *chibios_alloc(void *heap, int size);
void chibios_free(void *ptr);

#define XREALLOC(p,n,h,t)   chHeapRealloc( (p) , (n) )
#define XMALLOC(s,h,t)      chibios_alloc(h,s)
#define XFREE(p,h,t)        chibios_free(p)

/* Re-mapping file system functions */
#if defined WOLFSSL_USER_FILESYSTEM
  #define XFILE     int32_t *
  #define XFOPEN    chibios_fopen
  #define XFSEEK    chibios_fseek
  #define XFTELL    chibios_ftell
  #define XREWIND   chibios_rewind
  #define XFREAD    chibios_fread
  #define XFWRITE   chibios_fwrite
  #define XFCLOSE   chibios_fclose
  #define XSEEK_END SEEK_END
  #define XBADFILE  NULL
  #define XFGETS(A,B,C)   NULL
  #define XGETENV(A)   NULL

  XFILE  chibios_fopen(const char *filename, const char *mode);
  int    chibios_fseek(XFILE file, long offset, int whence);
  long   chibios_ftell(XFILE file);
  void   chibios_rewind(XFILE file);
  size_t chibios_fread(void *ptr, size_t size, size_t nmemb, XFILE file);
  size_t chibios_fwrite(void *ptr, size_t size, size_t nmemb, XFILE file);
  int    chibios_fclose(XFILE file);
#endif

Share

Re: RSA encryption

Add info
The function cryerror_t sama_rsa_lld_exponentiation(CRYDriver *cryp, rsacontext *rsactxp,uint8_t u1Mode, uint8_t * pu1Message)
fails the following step
        // Testing if Modulus is present
        if (!(rsactxp->u2FieldIsPresent & MODULUS_IS_PRESENT))
        {
            rsactxp->lastResult = ERR_MODULUS;
            return CRY_ERR_INV_ALGO;
        }

Share

Re: RSA encryption

Good news.
I find the iussue.
Missing wc_InitRsaKey_ex() before to call wc_RsaPublicKeyDecodeRaw().
Sorry for your time spent.
Thanks
Alex

Share