# MSC30-C: Do not use the rand() function for generating pseudorandom numbers

This query implements the CERT-C rule MSC30-C:

> Do not use the rand() function for generating pseudorandom numbers


## Description

Pseudorandom number generators use mathematical algorithms to produce a sequence of numbers with good statistical properties, but the numbers produced are not genuinely random.

The C Standard `rand()` function makes no guarantees as to the quality of the random sequence produced. The numbers generated by some implementations of `rand()` have a comparatively short cycle and the numbers can be predictable. Applications that have strong pseudorandom number requirements must use a generator that is known to be sufficient for their needs.

## Noncompliant Code Example

The following noncompliant code generates an ID with a numeric part produced by calling the `rand()` function. The IDs produced are predictable and have limited randomness.

```cpp
#include <stdio.h>
#include <stdlib.h>
 
enum { len = 12 };
 
void func(void) {
  /*
   * id will hold the ID, starting with the characters
   *  "ID" followed by a random integer.
   */
  char id[len];  
  int r;
  int num;
  /* ... */
  r = rand();  /* Generate a random integer */
  num = snprintf(id, len, "ID%-d", r);  /* Generate the ID */
  /* ... */
}
```

## Compliant Solution (POSIX)

This compliant solution replaces the `rand()` function with the POSIX `random()` function:

```cpp
#include <stdio.h>
#include <stdlib.h>
#include <time.h>

enum { len = 12 }; 

void func(void) {
  /*
   * id will hold the ID, starting with the characters
   *  "ID" followed by a random integer.
   */
  char id[len];  
  int r;
  int num;
  /* ... */
  struct timespec ts;
  if (timespec_get(&ts, TIME_UTC) == 0) {
    /* Handle error */
  }
  srandom(ts.tv_nsec ^ ts.tv_sec);  /* Seed the PRNG */
  /* ... */
  r = random();  /* Generate a random integer */
  num = snprintf(id, len, "ID%-d", r);  /* Generate the ID */
  /* ... */
}
```
The POSIX `random()` function is a better pseudorandom number generator. Although on some platforms the low dozen bits generated by `rand()` go through a cyclic pattern, all the bits generated by `random()` are usable. The `rand48` family of functions provides another alternative for pseudorandom numbers.

Although not specified by POSIX, [arc4random()](http://www.openbsd.org/cgi-bin/man.cgi?query=arc4random) is another possibility for systems that support it. The `arc4random(3)` manual page \[[OpenBSD](https://wiki.sei.cmu.edu/confluence/display/c/AA.+Bibliography#AA.Bibliography-OpenBSD)\] states

> ... provides higher quality of data than those described in rand(3), random(3), and drand48(3).


To achieve the best random numbers possible, an [implementation](https://wiki.sei.cmu.edu/confluence/display/c/BB.+Definitions#BB.Definitions-implementation)-specific function must be used. When unpredictability is crucial and speed is not an issue, as in the creation of strong cryptographic keys, use a true entropy source, such as `/dev/random`, or a hardware device capable of generating random numbers. The `/dev/random` device can block for a long time if there are not enough events going on to generate sufficient entropy.

## Compliant Solution (Windows)

On Windows platforms, the [BCryptGenRandom()](https://docs.microsoft.com/en-us/windows/desktop/api/bcrypt/nf-bcrypt-bcryptgenrandom) function can be used to generate cryptographically strong random numbers. The Microsoft Developer Network `BCryptGenRandom()` reference \[[MSDN](https://wiki.sei.cmu.edu/confluence/display/c/AA.+Bibliography#AA.Bibliography-MSDN)\] states:

> The default random number provider implements an algorithm for generating random numbers that complies with the NIST SP800-90 standard, specifically the CTR_DRBG portion of that standard.


```cpp
#include <Windows.h>
#include <bcrypt.h>
#include <stdio.h>

#pragma comment(lib, "Bcrypt")

void func(void) {
  BCRYPT_ALG_HANDLE Prov;
  int Buffer;
  if (!BCRYPT_SUCCESS(
          BCryptOpenAlgorithmProvider(&Prov, BCRYPT_RNG_ALGORITHM,
                                      NULL, 0))) {
    /* handle error */
  }
  if (!BCRYPT_SUCCESS(BCryptGenRandom(Prov, (PUCHAR) (&Buffer),
                                      sizeof(Buffer), 0))) {
    /* handle error */
  }
  printf("Random number: %d\n", Buffer);
  BCryptCloseAlgorithmProvider(Prov, 0);
}
```

## Risk Assessment

The use of the `rand()` function can result in predictable random numbers.

<table> <tbody> <tr> <th> Rule </th> <th> Severity </th> <th> Likelihood </th> <th> Remediation Cost </th> <th> Priority </th> <th> Level </th> </tr> <tr> <td> MSC30-C </td> <td> Medium </td> <td> Unlikely </td> <td> Low </td> <td> <strong>P6</strong> </td> <td> <strong>L2</strong> </td> </tr> </tbody> </table>


## Automated Detection

<table> <tbody> <tr> <th> Tool </th> <th> Version </th> <th> Checker </th> <th> Description </th> </tr> <tr> <td> <a> Astrée </a> </td> <td> 22.04 </td> <td> <strong>stdlib-use-rand</strong> </td> <td> Fully checked </td> </tr> <tr> <td> <a> Axivion Bauhaus Suite </a> </td> <td> 7.2.0 </td> <td> <strong>CertC-MSC30</strong> </td> <td> </td> </tr> <tr> <td> <a> Clang </a> </td> <td> 4.0 (prerelease) </td> <td> <code>cert-msc30-c</code> </td> <td> Checked by <code>clang-tidy</code> </td> </tr> <tr> <td> <a> CodeSonar </a> </td> <td> 7.0p0 </td> <td> <strong>BADFUNC.RANDOM.RAND</strong> </td> <td> Use of rand </td> </tr> <tr> <td> <a> Compass/ROSE </a> </td> <td> </td> <td> </td> <td> </td> </tr> <tr> <td> <a> Coverity </a> </td> <td> 2017.07 </td> <td> <strong>DONTCALL</strong> </td> <td> Implemented - weak support </td> </tr> <tr> <td> <a> ECLAIR </a> </td> <td> 1.2 </td> <td> <strong>CC2.MSC30</strong> </td> <td> Fully implemented </td> </tr> <tr> <td> <a> Helix QAC </a> </td> <td> 2022.2 </td> <td> <strong>C5022</strong> <strong>C++5029</strong> </td> <td> </td> </tr> <tr> <td> <a> Klocwork </a> </td> <td> 2022.2 </td> <td> <strong>CERT.MSC.STD_RAND_CALL</strong> </td> <td> </td> </tr> <tr> <td> <a> LDRA tool suite </a> </td> <td> 9.7.1 </td> <td> <strong>44 S</strong> </td> <td> Enhanced enforcement </td> </tr> <tr> <td> <a> Parasoft C/C++test </a> </td> <td> 2022.1 </td> <td> <strong>CERT_C-MSC30-a</strong> </td> <td> Do not use the rand() function for generating pseudorandom numbers </td> </tr> <tr> <td> <a> PC-lint Plus </a> </td> <td> 1.4 </td> <td> <strong>586</strong> </td> <td> Fully supported </td> </tr> <tr> <td> <a> Polyspace Bug Finder </a> </td> <td> R2022a </td> <td> <a> CERT C: Rule MSC30-C </a> </td> <td> Checks for vulnerable pseudo-random number generator (rule fully covered) </td> </tr> <tr> <td> <a> PRQA QA-C </a> </td> <td> 9.7 </td> <td> <strong>5022</strong> </td> <td> Fully implemented </td> </tr> <tr> <td> <a> PRQA QA-C++ </a> </td> <td> 4.4 </td> <td> <strong>5029</strong> </td> <td> </td> </tr> <tr> <td> <a> RuleChecker </a> </td> <td> 22.04 </td> <td> <strong>stdlib-use-rand</strong> </td> <td> Fully checked </td> </tr> </tbody> </table>


## Related Vulnerabilities

Search for [vulnerabilities](https://wiki.sei.cmu.edu/confluence/display/c/BB.+Definitions#BB.Definitions-vulnerability) resulting from the violation of this rule on the [CERT website](https://www.kb.cert.org/vulnotes/bymetric?searchview&query=FIELD+KEYWORDS+contains+MSC30-C).

## Related Guidelines

[Key here](https://wiki.sei.cmu.edu/confluence/display/c/How+this+Coding+Standard+is+Organized#HowthisCodingStandardisOrganized-RelatedGuidelines) (explains table format and definitions)

<table> <tbody> <tr> <th> Taxonomy </th> <th> Taxonomy item </th> <th> Relationship </th> </tr> <tr> <td> <a> CERT C </a> </td> <td> <a> MSC50-CPP. Do not use std::rand() for generating pseudorandom numbers </a> </td> <td> Prior to 2018-01-12: CERT: Unspecified Relationship </td> </tr> <tr> <td> <a> CERT Oracle Secure Coding Standard for Java </a> </td> <td> <a> MSC02-J. Generate strong random numbers </a> </td> <td> Prior to 2018-01-12: CERT: Unspecified Relationship </td> </tr> <tr> <td> <a> CWE 2.11 </a> </td> <td> <a> CWE-327 </a> , Use of a Broken or Risky Cryptographic Algorithm </td> <td> 2017-05-16: CERT: Rule subset of CWE </td> </tr> <tr> <td> <a> CWE 2.11 </a> </td> <td> <a> CWE-330 </a> , Use of Insufficiently Random Values </td> <td> 2017-06-28: CERT: Rule subset of CWE </td> </tr> <tr> <td> <a> CWE 2.11 </a> </td> <td> <a> CWE-338 </a> , Use of Cryptographically Weak Pseudo-Random Number Generator (PRNG) </td> <td> 2017-06-28: CERT: Rule subset of CWE </td> </tr> <tr> <td> <a> CWE 2.11 </a> </td> <td> <a> CWE-676 </a> </td> <td> 2017-05-18: CERT: Rule subset of CWE </td> </tr> </tbody> </table>


## CERT-CWE Mapping Notes

[Key here](https://wiki.sei.cmu.edu/confluence/pages/viewpage.action?pageId=87152408#HowthisCodingStandardisOrganized-CERT-CWEMappingNotes) for mapping notes

**CWE-327 and MSC30-C**

* CWE-327 forbids “broken or risky cryptographic algorithms” but does not specify what constitutes such an algo.
* Per CERT judgement, rand() qualifies, so:
* CWE-327 = Union( MSC30-C, list) where list =
* Invocation of broken/risky crypto algorithms besides rand()
**CWE-338 and MSC30-C**

CWE-338 = Union( MSC30-C, list) where list =

* Use of a weak PRNG besides standard C rand().
**CWE-330 and MSC30-C**

Independent( MSC30-C, MSC32-C, CON33-C)

CWE-330 = Union( MSC30-C, MSC32-C, CON33-C, list) where list = other improper use or creation of random values. (EG the would qualify)

MSC30-C, MSC32-C and CON33-C are independent, they have no intersections. They each specify distinct errors regarding PRNGs.

**CWE-676 and MSC30-C**

* Independent( ENV33-C, CON33-C, STR31-C, EXP33-C, MSC30-C, ERR34-C)
* MSC30-C implies that rand() is dangerous.
* CWE-676 = Union( MSC30-C, list) where list =
* Invocation of other dangerous functions, besides rand().

## Bibliography

<table> <tbody> <tr> <td> \[ <a> MSDN </a> \] </td> <td> " <a> BCryptGenRandom() Function </a> " </td> </tr> <tr> <td> \[ <a> OpenBSD </a> \] </td> <td> <a> arc4random() </a> </td> </tr> </tbody> </table>


## Implementation notes

None

## References

* CERT-C: [MSC30-C: Do not use the rand() function for generating pseudorandom numbers](https://wiki.sei.cmu.edu/confluence/display/c)
