CWE Rule 311
Description
Rule Description
The software does not encrypt sensitive or critical information before storage or transmission.
Polyspace Implementation
The rule checker checks for these issues:
Missing cipher algorithm
Missing cipher data to process
Missing cipher final step
Missing cipher key
Examples
Missing cipher algorithm
This issue occurs when you do not assign a cipher algorithm when setting up your cipher context.
You can initialize your cipher context without an algorithm. However, before you encrypt or decrypt your data, you must associate the cipher context with a cipher algorithm.
A missing cipher algorithm can lead to run-time errors or at least, non-secure ciphertext.
Before encryption or decryption, you set up a cipher context that has the information required for encryption: the cipher algorithm and mode, an encryption or decryption key and an initialization vector (for modes that require initialization vectors).
ret = EVP_EncryptInit(&ctx, EVP_aes_128_cbc(), key, iv)
EVP_aes_128_cbc()
specifies that
the Advanced Encryption Standard (AES) algorithm must be
used for encryption. The function also specifies a block
size of 128 bits and the Cipher Bloch Chaining (CBC)
mode.Instead of specifying the algorithm, you can use NULL in the initialization step. However, before using the cipher context for encryption or decryption, you must perform an additional initialization that associates an algorithm with the context. Otherwise, the update steps for encryption or decryption can lead to run-time errors.
Before your encryption or decryption steps
ret = EVP_EncryptUpdate(&ctx, out_buf, &out_len, src, len)
ctx
with an
algorithm.ret = EVP_EncryptInit(ctx, EVP_aes_128_cbc(), key, iv)
#include <openssl/evp.h> #include <stdlib.h> #define SIZE16 16 unsigned char key[SIZE16]; unsigned char iv[SIZE16]; void func(void) { EVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new(); EVP_CIPHER_CTX_init(ctx); EVP_EncryptInit_ex(ctx, NULL, NULL, key, iv); //Noncompliant }
In this example, an algorithm is not provided when the cipher
context ctx
is initialized.
Before you encrypt or decrypt your data, you have to provide
a cipher algorithm. If you perform a second initialization to provide
the algorithm, the cipher context is completely re-initialized. Therefore,
the current initialization statement using EVP_EncryptInit_ex
is
redundant.
One possible correction is to provide an algorithm when you
initialize the cipher context. In the corrected code below, the routine EVP_aes_128_cbc
invokes
the Advanced Encryption Standard (AES) algorithm. The routine also
specifies a block size of 128 bits and the Cipher Block Chaining (CBC)
mode for encryption.
#include <openssl/evp.h> #include <stdlib.h> #define SIZE16 16 unsigned char key[SIZE16]; unsigned char iv[SIZE16]; void func(unsigned char *src, int len, unsigned char *out_buf, int out_len) { EVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new(); EVP_CIPHER_CTX_init(ctx); /* Initialization of cipher context */ EVP_EncryptInit_ex(ctx, EVP_aes_128_cbc(), NULL, key, iv); //Compliant /* Update steps for encryption */ EVP_EncryptUpdate(ctx, out_buf, &out_len, src, len); }
Missing cipher data to process
This issue occurs when you perform the final step of a block cipher encryption or decryption incorrectly.
For instance, you do one of the following:
You do not perform update steps for encrypting or decrypting the data before performing a final step.
/* Initialization of cipher context */ ret = EVP_EncryptInit_ex(ctx, EVP_aes_128_cbc(), NULL, key, iv); ... /* Missing update step */ ... /* Final step */ ret = EVP_EncryptFinal_ex(ctx, out_buf, &out_len);
You perform consecutive final steps without intermediate initialization and update steps.
/* Initialization of cipher context */ ret = EVP_EncryptInit_ex(ctx, EVP_aes_128_cbc(), NULL, key, iv); ... /* Update step(s) */ ret = EVP_EncryptUpdate(ctx, out_buf, &out_len, src, len); ... /* Final step */ ret = EVP_EncryptFinal_ex(ctx, out_buf, &out_len); ... /* Missing initialization and update */ ... /* Second final step */ ret = EVP_EncryptFinal_ex(ctx, out_buf, &out_len);
You perform a cleanup of the cipher context and then perform a final step.
/* Initialization of cipher context */ ret = EVP_EncryptInit_ex(ctx, EVP_aes_128_cbc(), NULL, key, iv); ... /* Update step(s) */ ret = EVP_EncryptUpdate(ctx, out_buf, &out_len, src, len); ... /* Cleanup of cipher context */ EVP_CIPHER_CTX_cleanup(ctx); ... /* Second final step */ ret = EVP_EncryptFinal_ex(ctx, out_buf, &out_len);
Block ciphers break your data into blocks of fixed size. During encryption or decryption, the update step encrypts or decrypts your data in blocks. Any leftover data is encrypted or decrypted by the final step. The final step adds padding to the leftover data so that it occupies one block, and then encrypts or decrypts the padded data.
If you perform the final step before performing the update steps, or perform the final step when there is no data to process, the behavior is undefined. You can also encounter run-time errors.
Perform encryption or decryption in this sequence:
Initialization of cipher context
Update steps
Final step
Cleanup of context
#include <openssl/evp.h> #include <stdlib.h> #define SIZE16 16 unsigned char *out_buf; int out_len; unsigned char key[SIZE16]; unsigned char iv[SIZE16]; void func(void) { EVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new(); EVP_CIPHER_CTX_init(ctx); /* Initialization of cipher context */ EVP_EncryptInit_ex(ctx, EVP_aes_128_cbc(), NULL, key, iv); /* Missing update steps for encryption */ /* Final encryption step */ EVP_EncryptFinal_ex(ctx, out_buf, &out_len); //Noncompliant }
In this example, after the cipher context is initialized, there are no update steps for encrypting the data. The update steps are supposed to encrypt one or more blocks of data, leaving the final step to encrypt data that is left over in a partial block. If you perform the final step without previous update steps, the behavior is undefined.
Perform update steps for encryption before the final step. In
the corrected code below, the routine EVP_EncryptUpdate
performs
the update steps.
#include <openssl/evp.h> #include <stdlib.h> #define SIZE16 16 unsigned char *out_buf; int out_len; unsigned char key[SIZE16]; unsigned char iv[SIZE16]; void func(unsigned char *src, int len) { EVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new(); EVP_CIPHER_CTX_init(ctx); /* Initialization of cipher context */ EVP_EncryptInit_ex(ctx, EVP_aes_128_cbc(), NULL, key, iv); /* Update steps for encryption */ EVP_EncryptUpdate(ctx, out_buf, &out_len, src, len); /* Final encryption step */ EVP_EncryptFinal_ex(ctx, out_buf, &out_len); //Compliant }
Missing cipher final step
This issue occurs when you do not perform a final step after your update steps for encrypting or decrypting data.
For instance, you do the following:
/* Initialization of cipher context */ ret = EVP_EncryptInit_ex(&ctx, EVP_aes_128_cbc(), NULL, key, iv); ... /* Update step */ ret = EVP_EncryptUpdate(&ctx, out_buf, &out_len, src, len); ... /* Missing final step */ ... /* Cleanup of cipher context */ EVP_CIPHER_CTX_cleanup(ctx);
Block ciphers break your data into blocks of fixed size. During encryption or decryption, the update step encrypts or decrypts your data in blocks. Any leftover data is encrypted or decrypted by the final step. The final step adds padding to the leftover data so that it occupies one block, and then encrypts or decrypts the padded data.
If you do not perform the final step, leftover data remaining in a partial block is not encrypted or decrypted. You can face incomplete or unexpected output.
After your update steps for encryption or decryption, perform a final step to encrypt or decrypt leftover data.
/* Initialization of cipher context */ ret = EVP_EncryptInit_ex(&ctx, EVP_aes_128_cbc(), NULL, key, iv); ... /* Update step(s) */ ret = EVP_EncryptUpdate(&ctx, out_buf, &out_len, src, len); ... /* Final step */ ret = EVP_EncryptFinal_ex(&ctx, out_buf, &out_len); ... /* Cleanup of cipher context */ EVP_CIPHER_CTX_cleanup(ctx);
#include <openssl/evp.h> #include <stdlib.h> #define SIZE16 16 unsigned char *out_buf; int out_len; unsigned char key[SIZE16]; unsigned char iv[SIZE16]; void func(unsigned char *src, int len) { EVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new(); EVP_CIPHER_CTX_init(ctx); /* Initialization of cipher context */ EVP_EncryptInit_ex(ctx, EVP_aes_128_cbc(), NULL, key, iv); /* Update steps for encryption */ EVP_EncryptUpdate(ctx, out_buf, &out_len, src, len); /* Missing final encryption step */ /* Cleanup of cipher context */ EVP_CIPHER_CTX_cleanup(ctx); //Noncompliant }
In this example, the cipher context ctx
is
cleaned up before a final encryption step. The final step is supposed
to encrypt leftover data. Without the final step, the encryption is
incomplete.
After your update steps for encryption, perform a final encryption
step to encrypt leftover data. In the corrected code below, the routine EVP_EncryptFinal_ex
is
used to perform this final step.
#include <openssl/evp.h> #include <stdlib.h> #define SIZE16 16 unsigned char *out_buf; int out_len; unsigned char key[SIZE16]; unsigned char iv[SIZE16]; void func(unsigned char *src, int len) { EVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new(); EVP_CIPHER_CTX_init(ctx); /* Initialization of cipher context */ EVP_EncryptInit_ex(ctx, EVP_aes_128_cbc(), NULL, key, iv); /* Update steps for encryption */ EVP_EncryptUpdate(ctx, out_buf, &out_len, src, len); /* Final encryption step */ EVP_EncryptFinal_ex(ctx, out_buf, &out_len); /* Cleanup of cipher context */ EVP_CIPHER_CTX_cleanup(ctx); //Compliant }
Missing cipher key
This issue occurs when you encrypt or decrypt data using a NULL encryption or decryption key.
Note
You can initialize your cipher context with a NULL key. However, before you encrypt or decrypt your data, you must associate the cipher context with a non-NULL key.
Encryption or decryption with a NULL key can lead to run-time errors or at least, non-secure ciphertext.
Before your encryption or decryption steps
ret = EVP_EncryptUpdate(&ctx, out_buf, &out_len, src, len)
ctx
with a
non-NULL
key.ret = EVP_EncryptInit_ex(ctx, EVP_aes_128_cbc(), NULL, key, iv)
Sometimes, you initialize your cipher context with a non-NULL key
ret = EVP_EncryptInit_ex(&ctx, cipher_algo_1, NULL, key, iv)
ret = EVP_EncryptInit_ex(&ctx, cipher_algo_2, NULL, NULL, NULL)
#include <openssl/evp.h> #include <stdlib.h> #define fatal_error() abort() unsigned char *out_buf; int out_len; int func(EVP_CIPHER_CTX *ctx, unsigned char *iv, unsigned char *src, int len){ if (iv == NULL) fatal_error(); /* Fourth argument is cipher key */ EVP_EncryptInit_ex(ctx, EVP_aes_128_cbc(), NULL, NULL, iv); /* Update step with NULL key */ return EVP_EncryptUpdate(ctx, out_buf, &out_len, src, len); //Noncompliant }
In this example, the cipher key associated with the context ctx
is
NULL. When you use this context to encrypt your data, you can encounter
run-time errors.
Use a strong random number generator to produce the cipher key.
The corrected code here uses the function RAND_bytes
declared
in openssl/rand.h
.
#include <openssl/evp.h> #include <openssl/rand.h> #include <stdlib.h> #define fatal_error() abort() #define SIZE16 16 unsigned char *out_buf; int out_len; int func(EVP_CIPHER_CTX *ctx, unsigned char *iv, unsigned char *src, int len){ if (iv == NULL) fatal_error(); unsigned char key[SIZE16]; RAND_bytes(key, 16); /* Fourth argument is cipher key */ EVP_EncryptInit_ex(ctx, EVP_aes_128_cbc(), NULL, key, iv); /* Update step with non-NULL cipher key */ return EVP_EncryptUpdate(ctx, out_buf, &out_len, src, len); //Compliant }
Check Information
Category: Others |
Version History
Introduced in R2023b
See Also
External Websites
MATLAB Command
You clicked a link that corresponds to this MATLAB command:
Run the command by entering it in the MATLAB Command Window. Web browsers do not support MATLAB commands.
Select a Web Site
Choose a web site to get translated content where available and see local events and offers. Based on your location, we recommend that you select: .
You can also select a web site from the following list
How to Get Best Site Performance
Select the China site (in Chinese or English) for best site performance. Other MathWorks country sites are not optimized for visits from your location.
Americas
- América Latina (Español)
- Canada (English)
- United States (English)
Europe
- Belgium (English)
- Denmark (English)
- Deutschland (Deutsch)
- España (Español)
- Finland (English)
- France (Français)
- Ireland (English)
- Italia (Italiano)
- Luxembourg (English)
- Netherlands (English)
- Norway (English)
- Österreich (Deutsch)
- Portugal (English)
- Sweden (English)
- Switzerland
- United Kingdom (English)
Asia Pacific
- Australia (English)
- India (English)
- New Zealand (English)
- 中国
- 日本Japanese (日本語)
- 한국Korean (한국어)