CWE Rule 330
Description
Rule Description
The product uses insufficiently random numbers or values in a security context that depends on unpredictable numbers.
Polyspace Implementation
The rule checker checks for these issues:
Deterministic random output from constant seed
Predictable block cipher initialization vector
Predictable cipher key
Predictable random output from predictable seed
Vulnerable pseudo-random number generator
Examples
Deterministic random output from constant seed
This issue occurs when you use standard random number generator functions that have deterministic output given a constant seed.
The checker detects this issue with the following random number generator functions:
C Standard Library functions such as
srand
,srandom
andinitstate
OpenSSL functions such as
RAND_seed
andRAND_add
C++ Standard Library functions such as
std::linear_congruential_engine<>::seed()
andstd::mersenne_twister_engine<>::seed()
(and also the constructors of these class templates)
With constant seeds, random number generator functions produce the same output every time your program is run. A hacker can disrupt your program if they know how your program behaves.
Use a different random standard function or use a nonconstant seed.
Some standard random routines are inherently cryptographically weak, and should not be used for security purposes.
#include <stdlib.h> void random_num(void) { srand(12345U); //Noncompliant /* ... */ }
This example initializes a random number generator using srand
with
a constant seed. The random number generation is deterministic,
making this function cryptographically weak.
One possible correction is to use a random number generator
that does not require a seed. This example uses rand_s
.
#define _CRT_RAND_S #include <stdlib.h> #include <stdio.h> unsigned int random_num_time(void) { unsigned int number; errno_t err; err = rand_s(&number); if(err != 0) { return number; } else { return err; } }
Predictable block cipher initialization vector
This issue occurs when you use a weak random number generator for the block cipher initialization vector.
If you use a weak random number generator for the initiation vector, your data is vulnerable to dictionary attacks.
Block ciphers break your data into blocks of fixed size. Block cipher modes such as CBC (Cipher Block Chaining) protect against dictionary attacks by XOR-ing each block with the encrypted output from the previous block. To protect the first block, these modes use a random initialization vector (IV). If you use a weak random number generator for your IV, your data becomes vulnerable to dictionary attacks.
Use a strong pseudo-random number generator (PRNG) for the initialization vector. For instance, use:
OS-level PRNG such as
/dev/random
on UNIX® orCryptGenRandom()
on Windows®Application-level PRNG such as Advanced Encryption Standard (AES) in Counter (CTR) mode, HMAC-SHA1, etc.
For a list of random number generators that are cryptographically
weak, see Vulnerable pseudo-random
number generator
.
#include <openssl/evp.h> #include <openssl/rand.h> #include <stdlib.h> #define SIZE16 16 int func(EVP_CIPHER_CTX *ctx, unsigned char *key){ unsigned char iv[SIZE16]; RAND_pseudo_bytes(iv, 16);//Noncompliant return EVP_CipherInit_ex(ctx, EVP_aes_128_cbc(), NULL, key, iv, 1); //Noncompliant }
In this example, the function RAND_pseudo_bytes
declared
in openssl/rand.h
produces the initialization vector.
The byte sequences that RAND_pseudo_bytes
generates
are not necessarily unpredictable.
Use a strong random number generator to produce the initialization
vector. 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 SIZE16 16 int func(EVP_CIPHER_CTX *ctx, unsigned char *key){ unsigned char iv[SIZE16]; RAND_bytes(iv, 16); return EVP_CipherInit_ex(ctx, EVP_aes_128_cbc(), NULL, key, iv, 1); }
Predictable cipher key
This issue occurs when you use a weak random number generator for the encryption or decryption key.
If you use a weak random number generator for the encryption or decryption key, an attacker can retrieve your key easily.
You use a key to encrypt and later decrypt your data. If a key is easily retrieved, data encrypted using that key is not secure.
Use a strong pseudo-random number generator (PRNG) for the key. For instance:
Use an OS-level PRNG such as
/dev/random
on UNIX orCryptGenRandom()
on WindowsUse an application-level PRNG such as Advanced Encryption Standard (AES) in Counter (CTR) mode, HMAC-SHA1, etc.
For a list of random number generators that are cryptographically
weak, see Vulnerable pseudo-random
number generator
.
#include <openssl/evp.h> #include <openssl/rand.h> #include <stdlib.h> #define SIZE16 16 int func(EVP_CIPHER_CTX *ctx, unsigned char *iv){ unsigned char key[SIZE16]; RAND_pseudo_bytes(key, 16);//Noncompliant return EVP_CipherInit_ex(ctx, EVP_aes_128_cbc(), NULL, key, iv, 1); //Noncompliant }
In this example, the function RAND_pseudo_bytes
declared
in openssl/rand.h
produces the cipher key. However,
the byte sequences that RAND_pseudo_bytes
generates
are not necessarily unpredictable.
One possible correction is to 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 SIZE16 16 int func(EVP_CIPHER_CTX *ctx, unsigned char *iv){ unsigned char key[SIZE16]; RAND_bytes(key, 16); return EVP_CipherInit_ex(ctx, EVP_aes_128_cbc(), NULL, key, iv, 1); }
Predictable random output from predictable seed
This issue occurs when you use standard random number generator functions with a nonconstant
but predictable seed. Examples of predictable seed generators are
time
, gettimeofday
, and
getpid
.
The checker detects this issue with the following random number generator functions:
C Standard Library functions such as
srand
,srandom
andinitstate
C++ Standard Library functions such as
std::linear_congruential_engine<>::seed()
andstd::mersenne_twister_engine<>::seed()
(and also the constructors of these class templates)
When you use predictable seed values for random number generation, your random numbers are also predictable. A hacker can disrupt your program if they know how your program behaves.
You can use a different function to generate less predictable seeds.
You can also use a different random number generator that does
not require a seed. For example, the Windows API function rand_s
seeds
itself by default. It uses information from the entire system, for
example, system time, thread ids, system counter, and memory clusters.
This information is more random and a user cannot access this information.
Some standard random routines are inherently cryptographically weak, and should not be used for security purposes.
#include <stdlib.h> #include <time.h> void seed_rng(int seed) { srand(seed); //Noncompliant } int generate_num(void) { seed_rng(time(NULL) + 3); /* ... */ }
This example uses srand
to start the random
number generator with seed
as the seed. However, seed
is
predictable because the function time
generates
it. So, an attacker can predict the random numbers generated by srand
.
One possible correction is to use a random number generator
that does not require a seed. This example uses rand_s
.
#define _CRT_RAND_S #include <stdlib.h> #include <stdio.h> #include <errno.h> int generate_num(void) { unsigned int number; errno_t err; err = rand_s(&number); if(err != 0) { return number; } else { return err; } }
Vulnerable pseudo-random number generator
This issue occurs when you use cryptographically weak pseudo-random number generator (PRNG) routines.
The list of cryptographically weak routines flagged by this checker include:
rand
,random
drand48
,lrand48
,mrand48
,erand48
,nrand48
,jrand48
, and their_r
equivalents such asdrand48_r
RAND_pseudo_bytes
These cryptographically weak routines are predictable and must not be used for security purposes. When a predictable random value controls the execution flow, your program is vulnerable to malicious attacks.
Use more cryptographically sound random number generators, such
as CryptGenRandom
(Windows), OpenSSL/RAND_bytes
(Linux/UNIX).
#include <stdio.h> #include <stdlib.h> volatile int rd = 1; int main(int argc, char *argv[]) { int j, r, nloops; struct random_data buf; int i = 0; nloops = rand(); //Noncompliant for (j = 0; j < nloops; j++) { if (random_r(&buf, &i)) //Noncompliant exit(1); printf("random_r: %ld\n", (long)i); } return 0; }
This example uses the functions rand()
and random_r()
to generate random numbers. If you use these functions for security purposes, these PRNGs can be the source of malicious attacks.
One possible correction is to replace the vulnerable PRNG with a stronger random number generator.
#include <stdio.h> #include <stdlib.h> #include <openssl/rand.h> volatile int rd = 1; int main(int argc, char* argv[]) { int j, r, nloops; unsigned char buf; unsigned int seed; int i = 0; if (argc != 3) { fprintf(stderr, "Usage: %s <seed> <nloops>\n", argv[0]); exit(EXIT_FAILURE); } seed = atoi(argv[1]); nloops = atoi(argv[2]); for (j = 0; j < nloops; j++) { if (RAND_bytes(&buf, i) != 1) exit(1); printf("RAND_bytes: %u\n", (unsigned)buf); } return 0; }
Check Information
Category: Others |
Version History
Introduced in R2024a
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 (한국어)