1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
//! This module implements a check for CWE332: Insufficient Entropy in PRNG.
//!
//! This can happen, for instance, if the PRNG is not seeded. A classical example
//! would be calling rand without srand. This could lead to predictable random
//! numbers and could, for example, weaken crypto functionality.
//!
//! See <https://cwe.mitre.org/data/definitions/332.html> for a detailed description.
//!
//! ## How the check works
//!
//! For pairs of a secure seeding function and a corresponding random number generator function
//! (e.g. the pair `(srand, rand)`, configurable in `config.json`)
//! we check whether the program calls the random number generator without calling the seeding function.
//!
//! ## False Positives
//!
//! None known
//!
//! ## False Negatives
//!
//! - It is not checked whether the seeding function gets called before the random number generator function.
use crate::intermediate_representation::*;
use crate::prelude::*;
use crate::utils::log::{CweWarning, LogMessage};
use crate::utils::symbol_utils::find_symbol;
use crate::CweModule;
pub static CWE_MODULE: CweModule = CweModule {
name: "CWE332",
version: "0.1",
run: check_cwe,
};
/// The configuration struct contains pairs of symbol names,
/// where the first name is the name of a seeding function
/// and the second name is the name of a corresponding random number generator access function.
/// It is assumed that a program has to call the seeding function first
/// to ensure that the RNG does not generate predictable random numbers.
#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Hash, Clone)]
pub struct Config {
pairs: Vec<(String, String)>,
}
/// Generate the CWE warning for a detected instance of the CWE.
fn generate_cwe_warning(secure_initializer_func: &str, rand_func: &str) -> CweWarning {
CweWarning::new(
CWE_MODULE.name,
CWE_MODULE.version,
format!(
"(Insufficient Entropy in PRNG) program uses {} without calling {} before",
rand_func, secure_initializer_func
),
)
}
/// Run the CWE check. See the module-level description for more information.
pub fn check_cwe(
project: &Project,
cwe_params: &serde_json::Value,
) -> (Vec<LogMessage>, Vec<CweWarning>) {
let config: Config = serde_json::from_value(cwe_params.clone()).unwrap();
let mut cwe_warnings = Vec::new();
for (secure_initializer_func, rand_func) in config.pairs.iter() {
if find_symbol(&project.program, rand_func).is_some()
&& find_symbol(&project.program, secure_initializer_func).is_none()
{
cwe_warnings.push(generate_cwe_warning(secure_initializer_func, rand_func));
}
}
(Vec::new(), cwe_warnings)
}