Main Content

CWE Rule 780

Use of RSA Algorithm without OAEP

Since R2024a

Description

Rule Description

The product uses the RSA algorithm but does not incorporate Optimal Asymmetric Encryption Padding (OAEP), which might weaken the encryption.

Polyspace Implementation

The rule checker checks for these issues:

  • Missing padding for RSA algorithm

  • Weak padding for RSA algorithm

Examples

expand all

Issue

This issue occurs when you perform RSA encryption or signature by using a context object without associating the object with a padding scheme.

For instance, you perform encryption by using a context object that was initially not associated with a specific padding.

ret = EVP_PKEY_CTX_set_rsa_padding(ctx, RSA_NO_PADDING);
...
ret = EVP_PKEY_encrypt(ctx, out, &out_len, in, in_len)

Risk

Padding schemes remove determinism from the RSA algorithm and protect RSA operations from certain kinds of attack. Padding ensures that a given message does not lead to the same ciphertext each time it is encrypted. Without padding, an attacker can launch chosen-plaintext attacks against the cryptosystem.

Fix

Before performing an RSA operation, associate the context object with a padding scheme that is compatible with the operation.

  • Encryption: Use the OAEP padding scheme.

    For instance, use the EVP_PKEY_CTX_set_rsa_padding function with the argument RSA_PKCS1_OAEP_PADDING or the RSA_padding_add_PKCS1_OAEP function.

    ret = EVP_PKEY_CTX_set_rsa_padding(ctx, RSA_PKCS1_OAEP_PADDING);
    
    You can also use the PKCS#1v1.5 or SSLv23 schemes. Be aware that these schemes are considered insecure.

    You can then use functions such as EVP_PKEY_encrypt / EVP_PKEY_decrypt or RSA_public_encrypt / RSA_private_decrypt on the context.

  • Signature: Use the RSA-PSS padding scheme.

    For instance, use the EVP_PKEY_CTX_set_rsa_padding function with the argument RSA_PKCS1_PSS_PADDING.

    ret = EVP_PKEY_CTX_set_rsa_padding(ctx, RSA_PKCS1_PSS_PADDING);
    You can also use the ANSI X9.31, PKCS#1v1.5, or SSLv23 schemes. Be aware that these schemes are considered insecure.

    You can then use functions such as the EVP_PKEY_sign-EVP_PKEY_verify pair or the RSA_private_encrypt-RSA_public_decrypt pair on the context.

If you perform two kinds of operation with the same context, after the first operation, reset the padding scheme in the context before the second operation.

Example — Encryption Without Padding
#include <stddef.h>
#include <openssl/rsa.h>
#include <openssl/evp.h>

#define fatal_error() exit(-1)

int ret;
unsigned char *out_buf;
size_t out_len;


int func(unsigned char *src, size_t len){
  EVP_PKEY_CTX *ctx;
  EVP_PKEY* pkey;

  /* Key generation */
  ctx = EVP_PKEY_CTX_new_id(EVP_PKEY_RSA,NULL); 
  if (ctx == NULL) fatal_error();

  ret = EVP_PKEY_keygen_init(ctx);
  if (ret <= 0) fatal_error();
  ret = EVP_PKEY_CTX_set_rsa_keygen_bits(ctx, 2048);
  if (ret <= 0) fatal_error();
  ret = EVP_PKEY_keygen(ctx, &pkey);  
  if (ret <= 0) fatal_error();

  /* Encryption */
  EVP_PKEY_CTX_free(ctx);
  ctx = EVP_PKEY_CTX_new(pkey,NULL); 
  if (ctx == NULL) fatal_error();

  ret = EVP_PKEY_encrypt_init(ctx);
  if (ret <= 0) fatal_error();
  return EVP_PKEY_encrypt(ctx, out_buf, &out_len, src, len);  //Noncompliant
}

In this example, before encryption with EVP_PKEY_encrypt, a specific padding is not associated with the context object ctx.

Correction — Set Padding in Context Before Encryption

One possible correction is to set the OAEP padding scheme in the context.

#include <stddef.h>
#include <openssl/rsa.h>
#include <openssl/evp.h>

#define fatal_error() exit(-1)

int ret;
unsigned char *out_buf;
size_t out_len;


int func(unsigned char *src, size_t len){
  EVP_PKEY_CTX *ctx;
  EVP_PKEY* pkey;

  /* Key generation */
  ctx = EVP_PKEY_CTX_new_id(EVP_PKEY_RSA,NULL); 
  if (ctx == NULL) fatal_error();

  ret = EVP_PKEY_keygen_init(ctx);
  if (ret <= 0) fatal_error();
  ret = EVP_PKEY_CTX_set_rsa_keygen_bits(ctx, 2048);
  if (ret <= 0) fatal_error();
  ret = EVP_PKEY_keygen(ctx, &pkey);  
  if (ret <= 0) fatal_error();

  /* Encryption */
  EVP_PKEY_CTX_free(ctx);
  ctx = EVP_PKEY_CTX_new(pkey,NULL); 
  if (ctx == NULL) fatal_error();

  ret = EVP_PKEY_encrypt_init(ctx);
  ret = EVP_PKEY_CTX_set_rsa_padding(ctx, RSA_PKCS1_OAEP_PADDING); 
  if (ret <= 0) fatal_error();
  if (ret <= 0) fatal_error();
  return EVP_PKEY_encrypt(ctx, out_buf, &out_len, src, len); 
}
Issue

This issue occurs when you perform RSA encryption or signature by using a context object that was previously associated with a weak padding scheme.

For instance, you perform encryption by using a context object that is associated with the PKCS#1v1.5 padding scheme. The scheme is considered insecure and has already been broken.

ret = EVP_PKEY_CTX_set_rsa_padding(ctx, RSA_PKCS1_PADDING);
...
ret = EVP_PKEY_encrypt(ctx, out, &out_len, in, in_len)

Risk

Padding schemes remove determinism from the RSA algorithm and protect RSA operations from certain kinds of attacks. Padding schemes such as PKCS#1v1.5, ANSI X9.31, and SSLv23 are known to be vulnerable. Do not use these padding schemes for encryption or signature operations.

Fix

Before performing an RSA operation, associate the context object with a strong padding scheme.

  • Encryption: Use the OAEP padding scheme.

    For instance, use the EVP_PKEY_CTX_set_rsa_padding function with the argument RSA_PKCS1_OAEP_PADDING or the RSA_padding_add_PKCS1_OAEP function.

    ret = EVP_PKEY_CTX_set_rsa_padding(ctx, RSA_PKCS1_OAEP_PADDING);
    

    You can then use functions such as EVP_PKEY_encrypt / EVP_PKEY_decrypt or RSA_public_encrypt / RSA_private_decrypt on the context.

  • Signature: Use the RSA-PSS padding scheme.

    For instance, use the EVP_PKEY_CTX_set_rsa_padding function with the argument RSA_PKCS1_PSS_PADDING.

    ret = EVP_PKEY_CTX_set_rsa_padding(ctx, RSA_PKCS1_PSS_PADDING);

    You can then use functions such as the EVP_PKEY_sign-EVP_PKEY_verify pair or the RSA_private_encrypt-RSA_public_decrypt pair on the context.

Example — Encryption with PKCS#1v1.5 Padding
#include <stddef.h>
#include <openssl/rsa.h>
#include <openssl/evp.h>

#define fatal_error() exit(-1)

int ret;
unsigned char *out_buf;

int func(unsigned char *src, size_t len, RSA* rsa){
  if (rsa == NULL) fatal_error(); 

  return RSA_public_encrypt(len, src, out_buf, rsa, RSA_PKCS1_PADDING);  //Noncompliant
}

In this example, the PKCS#1v1.5 padding scheme is used in the encryption step.

Correction — Use OAEP Padding Scheme

Use the OAEP padding scheme for stronger encryption.

#include <stddef.h>
#include <openssl/rsa.h>
#include <openssl/evp.h>

#define fatal_error() exit(-1)

int ret;
unsigned char *out_buf;

int func(unsigned char *src, size_t len, RSA* rsa){
  if (rsa == NULL) fatal_error(); 

  return RSA_public_encrypt(len, src, out_buf, rsa, RSA_PKCS1_OAEP_PADDING); 
}

Check Information

Category: Others

Version History

Introduced in R2024a