diff --git a/cpp/ql/test/query-tests/Microsoft/Likely Bugs/Drivers/IncorrectUsageOfRtlCompareMemory.expected b/cpp/ql/test/query-tests/Microsoft/Likely Bugs/Drivers/IncorrectUsageOfRtlCompareMemory.expected new file mode 100644 index 000000000000..812f7dffd433 --- /dev/null +++ b/cpp/ql/test/query-tests/Microsoft/Likely Bugs/Drivers/IncorrectUsageOfRtlCompareMemory.expected @@ -0,0 +1,15 @@ +| test.c:29:6:29:46 | ... && ... | This $@ is being handled $@ instead of the number of matching bytes. Please review the usage of this function and consider replacing it with `RtlEqualMemory`. | test.c:29:15:29:30 | call to RtlCompareMemory | call to `RtlCompareMemory` | test.c:29:6:29:46 | ... && ... | as an operand in a binary logical operation | +| test.c:34:6:34:38 | ! ... | This $@ is being handled $@ instead of the number of matching bytes. Please review the usage of this function and consider replacing it with `RtlEqualMemory`. | test.c:34:7:34:22 | call to RtlCompareMemory | call to `RtlCompareMemory` | test.c:34:6:34:38 | ! ... | as an operand in an unary logical operation | +| test.c:39:6:39:21 | call to RtlCompareMemory | This $@ is being handled $@ instead of the number of matching bytes. Please review the usage of this function and consider replacing it with `RtlEqualMemory`. | test.c:39:6:39:21 | call to RtlCompareMemory | call to `RtlCompareMemory` | test.c:39:6:39:21 | call to RtlCompareMemory | as the controlling expression in an If statement | +| test.c:49:6:49:42 | ... == ... | This $@ is being handled $@ instead of the number of matching bytes. Please review the usage of this function and consider replacing it with `RtlEqualMemory`. | test.c:49:11:49:26 | call to RtlCompareMemory | call to `RtlCompareMemory` | test.c:49:6:49:42 | ... == ... | as an operand in an equality operation where the other operand is likely a boolean value (lower precision result, needs to be reviewed) | +| test.c:75:6:75:37 | (bool)... | This $@ is being handled $@ instead of the number of matching bytes. Please review the usage of this function and consider replacing it with `RtlEqualMemory`. | test.c:75:6:75:21 | call to RtlCompareMemory | call to `RtlCompareMemory` | test.c:75:6:75:37 | (bool)... | as a boolean | +| test.c:77:6:77:46 | ... == ... | This $@ is being handled $@ instead of the number of matching bytes. Please review the usage of this function and consider replacing it with `RtlEqualMemory`. | test.c:77:15:77:30 | call to RtlCompareMemory | call to `RtlCompareMemory` | test.c:77:6:77:46 | ... == ... | as an operand in an equality operation where the other operand is a boolean value (high precision result) | +| test.c:84:6:84:37 | (BOOLEAN)... | This $@ is being handled $@ instead of the number of matching bytes. Please review the usage of this function and consider replacing it with `RtlEqualMemory`. | test.c:84:6:84:21 | call to RtlCompareMemory | call to `RtlCompareMemory` | test.c:84:6:84:37 | (BOOLEAN)... | as a boolean | +| test.c:86:6:86:45 | ... == ... | This $@ is being handled $@ instead of the number of matching bytes. Please review the usage of this function and consider replacing it with `RtlEqualMemory`. | test.c:86:14:86:29 | call to RtlCompareMemory | call to `RtlCompareMemory` | test.c:86:6:86:45 | ... == ... | as an operand in an equality operation where the other operand is a boolean value (high precision result) | +| test.c:91:9:91:52 | ... && ... | This $@ is being handled $@ instead of the number of matching bytes. Please review the usage of this function and consider replacing it with `RtlEqualMemory`. | test.c:91:21:91:36 | call to RtlCompareMemory | call to `RtlCompareMemory` | test.c:91:9:91:52 | ... && ... | as an operand in a binary logical operation | +| test.cpp:18:6:18:46 | ... && ... | This $@ is being handled $@ instead of the number of matching bytes. Please review the usage of this function and consider replacing it with `RtlEqualMemory`. | test.cpp:18:15:18:30 | call to RtlCompareMemory | call to `RtlCompareMemory` | test.cpp:18:6:18:46 | ... && ... | as an operand in a binary logical operation | +| test.cpp:18:15:18:46 | (bool)... | This $@ is being handled $@ instead of the number of matching bytes. Please review the usage of this function and consider replacing it with `RtlEqualMemory`. | test.cpp:18:15:18:30 | call to RtlCompareMemory | call to `RtlCompareMemory` | test.cpp:18:15:18:46 | (bool)... | as a boolean | +| test.cpp:23:6:23:38 | ! ... | This $@ is being handled $@ instead of the number of matching bytes. Please review the usage of this function and consider replacing it with `RtlEqualMemory`. | test.cpp:23:7:23:22 | call to RtlCompareMemory | call to `RtlCompareMemory` | test.cpp:23:6:23:38 | ! ... | as an operand in an unary logical operation | +| test.cpp:23:7:23:38 | (bool)... | This $@ is being handled $@ instead of the number of matching bytes. Please review the usage of this function and consider replacing it with `RtlEqualMemory`. | test.cpp:23:7:23:22 | call to RtlCompareMemory | call to `RtlCompareMemory` | test.cpp:23:7:23:38 | (bool)... | as a boolean | +| test.cpp:28:9:28:52 | ... && ... | This $@ is being handled $@ instead of the number of matching bytes. Please review the usage of this function and consider replacing it with `RtlEqualMemory`. | test.cpp:28:21:28:36 | call to RtlCompareMemory | call to `RtlCompareMemory` | test.cpp:28:9:28:52 | ... && ... | as an operand in a binary logical operation | +| test.cpp:28:21:28:52 | (bool)... | This $@ is being handled $@ instead of the number of matching bytes. Please review the usage of this function and consider replacing it with `RtlEqualMemory`. | test.cpp:28:21:28:36 | call to RtlCompareMemory | call to `RtlCompareMemory` | test.cpp:28:21:28:52 | (bool)... | as a boolean | diff --git a/cpp/ql/test/query-tests/Microsoft/Likely Bugs/Drivers/IncorrectUsageOfRtlCompareMemory.qlref b/cpp/ql/test/query-tests/Microsoft/Likely Bugs/Drivers/IncorrectUsageOfRtlCompareMemory.qlref new file mode 100644 index 000000000000..629e248bce7e --- /dev/null +++ b/cpp/ql/test/query-tests/Microsoft/Likely Bugs/Drivers/IncorrectUsageOfRtlCompareMemory.qlref @@ -0,0 +1 @@ +Microsoft/Likely Bugs/Drivers/IncorrectUsageOfRtlCompareMemory.ql \ No newline at end of file diff --git a/cpp/ql/test/query-tests/Microsoft/Likely Bugs/Drivers/test.c b/cpp/ql/test/query-tests/Microsoft/Likely Bugs/Drivers/test.c new file mode 100644 index 000000000000..cf3b006d0030 --- /dev/null +++ b/cpp/ql/test/query-tests/Microsoft/Likely Bugs/Drivers/test.c @@ -0,0 +1,92 @@ +// semmle-extractor-options: --microsoft +typedef unsigned __int64 size_t; + +size_t RtlCompareMemory( + const void* Source1, + const void* Source2, + size_t Length +) +{ + return Length; +} + + +#define bool _Bool +#define false 0 +#define true 1 + +typedef unsigned char UCHAR; +typedef UCHAR BOOLEAN; // winnt +#define FALSE 0 +#define TRUE 1 + +int Test(const void* ptr) +{ + size_t t = RtlCompareMemory("test", ptr, 5); //OK + bool x; + BOOLEAN y; + + if (t > 0 && RtlCompareMemory("test", ptr, 5)) //bug + { + t++; + } + + if (!RtlCompareMemory("test", ptr, 4)) //bug + { + t--; + } + + if (RtlCompareMemory("test", ptr, 4)) //bug + { + t--; + } + + if (6 == RtlCompareMemory("test", ptr, 4)) //OK + { + t++; + } + + if (0 == RtlCompareMemory("test", ptr, 4)) // potentially a bug (lower precision) + { + t++; + } + + if (6 == RtlCompareMemory("test", ptr, 4) + 1) //OK + { + t++; + } + + if (0 == RtlCompareMemory("test", ptr, 4) + 1) // OK + { + t++; + } + + switch (RtlCompareMemory("test", ptr, 4)) + { + case 1: + t--; + break; + default: + t++; + } + + /// _Bool + + x = RtlCompareMemory("test", ptr, 4); // bug + + if (false == RtlCompareMemory("test", ptr, 4)) // bug + { + t++; + } + + // BOOLEAN + + y = RtlCompareMemory("test", ptr, 4); // bug + + if (TRUE == RtlCompareMemory("test", ptr, 4)) // bug + { + t++; + } + + return (t == 5) && RtlCompareMemory("test", ptr, 5); //bug +} diff --git a/cpp/ql/test/query-tests/Microsoft/Likely Bugs/Drivers/test.cpp b/cpp/ql/test/query-tests/Microsoft/Likely Bugs/Drivers/test.cpp new file mode 100644 index 000000000000..f876133c67aa --- /dev/null +++ b/cpp/ql/test/query-tests/Microsoft/Likely Bugs/Drivers/test.cpp @@ -0,0 +1,29 @@ +// semmle-extractor-options: --microsoft +typedef unsigned __int64 size_t; + +size_t RtlCompareMemory( + const void* Source1, + const void* Source2, + size_t Length +) +{ + return Length; +} + + +bool Test(const void* ptr) +{ + size_t t = RtlCompareMemory("test", ptr, 5); //OK + + if (t > 0 && RtlCompareMemory("test", ptr, 5)) //bug + { + t++; + } + + if (!RtlCompareMemory("test", ptr, 4)) //bug + { + t--; + } + + return (t == 5) && RtlCompareMemory("test", ptr, 5); //bug +} \ No newline at end of file diff --git a/cpp/ql/test/query-tests/Microsoft/Likely Bugs/SizeOfMisuse/ArgumentIsSizeofOrOperation.expected b/cpp/ql/test/query-tests/Microsoft/Likely Bugs/SizeOfMisuse/ArgumentIsSizeofOrOperation.expected new file mode 100644 index 000000000000..2099532f8f4a --- /dev/null +++ b/cpp/ql/test/query-tests/Microsoft/Likely Bugs/SizeOfMisuse/ArgumentIsSizeofOrOperation.expected @@ -0,0 +1,48 @@ +| test2.c:86:6:86:29 | sizeof() | $@: $@ of $@ inside sizeof. | test2.c:86:6:86:29 | sizeof() | binary operator | test2.c:64:6:64:11 | Test01 | Usage | test2.c:86:13:86:28 | ... / ... | binary operator | +| test2.c:86:6:86:29 | sizeof() | $@: $@ of $@ inside sizeof. | test2.c:86:6:86:29 | sizeof() | binary operator | test.c:64:6:64:11 | Test01 | Usage | test2.c:86:13:86:28 | ... / ... | binary operator | +| test2.c:93:6:93:30 | sizeof() | $@: $@ of $@ inside sizeof. | test2.c:93:6:93:30 | sizeof() | binary operator | test2.c:64:6:64:11 | Test01 | Usage | test2.c:93:13:93:29 | ... * ... | binary operator | +| test2.c:93:6:93:30 | sizeof() | $@: $@ of $@ inside sizeof. | test2.c:93:6:93:30 | sizeof() | binary operator | test.c:64:6:64:11 | Test01 | Usage | test2.c:93:13:93:29 | ... * ... | binary operator | +| test2.c:95:6:95:35 | sizeof() | $@: $@ of $@ inside sizeof. | test2.c:95:6:95:35 | sizeof() | binary operator | test2.c:64:6:64:11 | Test01 | Usage | test2.c:95:13:95:34 | ... * ... | binary operator | +| test2.c:95:6:95:35 | sizeof() | $@: $@ of $@ inside sizeof. | test2.c:95:6:95:35 | sizeof() | binary operator | test.c:64:6:64:11 | Test01 | Usage | test2.c:95:13:95:34 | ... * ... | binary operator | +| test2.c:98:6:98:31 | sizeof() | $@: $@ of $@ inside sizeof. | test2.c:98:6:98:31 | sizeof() | sizeof | test2.c:64:6:64:11 | Test01 | Usage | test2.c:98:13:98:30 | sizeof(int) | sizeof | +| test2.c:98:6:98:31 | sizeof() | $@: $@ of $@ inside sizeof. | test2.c:98:6:98:31 | sizeof() | sizeof | test.c:64:6:64:11 | Test01 | Usage | test2.c:98:13:98:30 | sizeof(int) | sizeof | +| test2.c:116:6:116:24 | sizeof() | $@: $@ of $@ inside sizeof. | test2.c:116:6:116:24 | sizeof() | sizeof | test2.c:64:6:64:11 | Test01 | Usage | test2.c:116:13:116:23 | sizeof(int) | sizeof | +| test2.c:116:6:116:24 | sizeof() | $@: $@ of $@ inside sizeof. | test2.c:116:6:116:24 | sizeof() | sizeof | test.c:64:6:64:11 | Test01 | Usage | test2.c:116:13:116:23 | sizeof(int) | sizeof | +| test2.c:117:6:117:18 | sizeof() | $@: $@ of $@ inside sizeof. | test2.c:117:6:117:18 | sizeof() | binary operator | test2.c:64:6:64:11 | Test01 | Usage | test2.c:117:13:117:17 | ... + ... | binary operator | +| test2.c:117:6:117:18 | sizeof() | $@: $@ of $@ inside sizeof. | test2.c:117:6:117:18 | sizeof() | binary operator | test.c:64:6:64:11 | Test01 | Usage | test2.c:117:13:117:17 | ... + ... | binary operator | +| test2.cpp:89:6:89:29 | sizeof() | $@: $@ of $@ inside sizeof. | test2.cpp:89:6:89:29 | sizeof() | binary operator | test2.cpp:66:6:66:11 | Test01 | Usage | test2.cpp:89:13:89:28 | ... / ... | binary operator | +| test2.cpp:89:6:89:29 | sizeof() | $@: $@ of $@ inside sizeof. | test2.cpp:89:6:89:29 | sizeof() | binary operator | test.cpp:66:6:66:11 | Test01 | Usage | test2.cpp:89:13:89:28 | ... / ... | binary operator | +| test2.cpp:96:6:96:30 | sizeof() | $@: $@ of $@ inside sizeof. | test2.cpp:96:6:96:30 | sizeof() | binary operator | test2.cpp:66:6:66:11 | Test01 | Usage | test2.cpp:96:13:96:29 | ... * ... | binary operator | +| test2.cpp:96:6:96:30 | sizeof() | $@: $@ of $@ inside sizeof. | test2.cpp:96:6:96:30 | sizeof() | binary operator | test.cpp:66:6:66:11 | Test01 | Usage | test2.cpp:96:13:96:29 | ... * ... | binary operator | +| test2.cpp:98:6:98:35 | sizeof() | $@: $@ of $@ inside sizeof. | test2.cpp:98:6:98:35 | sizeof() | binary operator | test2.cpp:66:6:66:11 | Test01 | Usage | test2.cpp:98:13:98:34 | ... * ... | binary operator | +| test2.cpp:98:6:98:35 | sizeof() | $@: $@ of $@ inside sizeof. | test2.cpp:98:6:98:35 | sizeof() | binary operator | test.cpp:66:6:66:11 | Test01 | Usage | test2.cpp:98:13:98:34 | ... * ... | binary operator | +| test2.cpp:101:6:101:31 | sizeof() | $@: $@ of $@ inside sizeof. | test2.cpp:101:6:101:31 | sizeof() | sizeof | test2.cpp:66:6:66:11 | Test01 | Usage | test2.cpp:101:13:101:30 | sizeof(int) | sizeof | +| test2.cpp:101:6:101:31 | sizeof() | $@: $@ of $@ inside sizeof. | test2.cpp:101:6:101:31 | sizeof() | sizeof | test.cpp:66:6:66:11 | Test01 | Usage | test2.cpp:101:13:101:30 | sizeof(int) | sizeof | +| test2.cpp:120:6:120:24 | sizeof() | $@: $@ of $@ inside sizeof. | test2.cpp:120:6:120:24 | sizeof() | sizeof | test2.cpp:66:6:66:11 | Test01 | Usage | test2.cpp:120:13:120:23 | sizeof(int) | sizeof | +| test2.cpp:120:6:120:24 | sizeof() | $@: $@ of $@ inside sizeof. | test2.cpp:120:6:120:24 | sizeof() | sizeof | test.cpp:66:6:66:11 | Test01 | Usage | test2.cpp:120:13:120:23 | sizeof(int) | sizeof | +| test2.cpp:121:6:121:18 | sizeof() | $@: $@ of $@ inside sizeof. | test2.cpp:121:6:121:18 | sizeof() | binary operator | test2.cpp:66:6:66:11 | Test01 | Usage | test2.cpp:121:13:121:17 | ... + ... | binary operator | +| test2.cpp:121:6:121:18 | sizeof() | $@: $@ of $@ inside sizeof. | test2.cpp:121:6:121:18 | sizeof() | binary operator | test.cpp:66:6:66:11 | Test01 | Usage | test2.cpp:121:13:121:17 | ... + ... | binary operator | +| test.c:86:6:86:29 | sizeof() | $@: $@ of $@ inside sizeof. | test.c:86:6:86:29 | sizeof() | binary operator | test2.c:64:6:64:11 | Test01 | Usage | test.c:86:13:86:28 | ... / ... | binary operator | +| test.c:86:6:86:29 | sizeof() | $@: $@ of $@ inside sizeof. | test.c:86:6:86:29 | sizeof() | binary operator | test.c:64:6:64:11 | Test01 | Usage | test.c:86:13:86:28 | ... / ... | binary operator | +| test.c:93:6:93:30 | sizeof() | $@: $@ of $@ inside sizeof. | test.c:93:6:93:30 | sizeof() | binary operator | test2.c:64:6:64:11 | Test01 | Usage | test.c:93:13:93:29 | ... * ... | binary operator | +| test.c:93:6:93:30 | sizeof() | $@: $@ of $@ inside sizeof. | test.c:93:6:93:30 | sizeof() | binary operator | test.c:64:6:64:11 | Test01 | Usage | test.c:93:13:93:29 | ... * ... | binary operator | +| test.c:95:6:95:35 | sizeof() | $@: $@ of $@ inside sizeof. | test.c:95:6:95:35 | sizeof() | binary operator | test2.c:64:6:64:11 | Test01 | Usage | test.c:95:13:95:34 | ... * ... | binary operator | +| test.c:95:6:95:35 | sizeof() | $@: $@ of $@ inside sizeof. | test.c:95:6:95:35 | sizeof() | binary operator | test.c:64:6:64:11 | Test01 | Usage | test.c:95:13:95:34 | ... * ... | binary operator | +| test.c:98:6:98:31 | sizeof() | $@: $@ of $@ inside sizeof. | test.c:98:6:98:31 | sizeof() | sizeof | test2.c:64:6:64:11 | Test01 | Usage | test.c:98:13:98:30 | sizeof(int) | sizeof | +| test.c:98:6:98:31 | sizeof() | $@: $@ of $@ inside sizeof. | test.c:98:6:98:31 | sizeof() | sizeof | test.c:64:6:64:11 | Test01 | Usage | test.c:98:13:98:30 | sizeof(int) | sizeof | +| test.c:116:6:116:24 | sizeof() | $@: $@ of $@ inside sizeof. | test.c:116:6:116:24 | sizeof() | sizeof | test2.c:64:6:64:11 | Test01 | Usage | test.c:116:13:116:23 | sizeof(int) | sizeof | +| test.c:116:6:116:24 | sizeof() | $@: $@ of $@ inside sizeof. | test.c:116:6:116:24 | sizeof() | sizeof | test.c:64:6:64:11 | Test01 | Usage | test.c:116:13:116:23 | sizeof(int) | sizeof | +| test.c:117:6:117:18 | sizeof() | $@: $@ of $@ inside sizeof. | test.c:117:6:117:18 | sizeof() | binary operator | test2.c:64:6:64:11 | Test01 | Usage | test.c:117:13:117:17 | ... + ... | binary operator | +| test.c:117:6:117:18 | sizeof() | $@: $@ of $@ inside sizeof. | test.c:117:6:117:18 | sizeof() | binary operator | test.c:64:6:64:11 | Test01 | Usage | test.c:117:13:117:17 | ... + ... | binary operator | +| test.cpp:89:6:89:29 | sizeof() | $@: $@ of $@ inside sizeof. | test.cpp:89:6:89:29 | sizeof() | binary operator | test2.cpp:66:6:66:11 | Test01 | Usage | test.cpp:89:13:89:28 | ... / ... | binary operator | +| test.cpp:89:6:89:29 | sizeof() | $@: $@ of $@ inside sizeof. | test.cpp:89:6:89:29 | sizeof() | binary operator | test.cpp:66:6:66:11 | Test01 | Usage | test.cpp:89:13:89:28 | ... / ... | binary operator | +| test.cpp:96:6:96:30 | sizeof() | $@: $@ of $@ inside sizeof. | test.cpp:96:6:96:30 | sizeof() | binary operator | test2.cpp:66:6:66:11 | Test01 | Usage | test.cpp:96:13:96:29 | ... * ... | binary operator | +| test.cpp:96:6:96:30 | sizeof() | $@: $@ of $@ inside sizeof. | test.cpp:96:6:96:30 | sizeof() | binary operator | test.cpp:66:6:66:11 | Test01 | Usage | test.cpp:96:13:96:29 | ... * ... | binary operator | +| test.cpp:98:6:98:35 | sizeof() | $@: $@ of $@ inside sizeof. | test.cpp:98:6:98:35 | sizeof() | binary operator | test2.cpp:66:6:66:11 | Test01 | Usage | test.cpp:98:13:98:34 | ... * ... | binary operator | +| test.cpp:98:6:98:35 | sizeof() | $@: $@ of $@ inside sizeof. | test.cpp:98:6:98:35 | sizeof() | binary operator | test.cpp:66:6:66:11 | Test01 | Usage | test.cpp:98:13:98:34 | ... * ... | binary operator | +| test.cpp:101:6:101:31 | sizeof() | $@: $@ of $@ inside sizeof. | test.cpp:101:6:101:31 | sizeof() | sizeof | test2.cpp:66:6:66:11 | Test01 | Usage | test.cpp:101:13:101:30 | sizeof(int) | sizeof | +| test.cpp:101:6:101:31 | sizeof() | $@: $@ of $@ inside sizeof. | test.cpp:101:6:101:31 | sizeof() | sizeof | test.cpp:66:6:66:11 | Test01 | Usage | test.cpp:101:13:101:30 | sizeof(int) | sizeof | +| test.cpp:120:6:120:24 | sizeof() | $@: $@ of $@ inside sizeof. | test.cpp:120:6:120:24 | sizeof() | sizeof | test2.cpp:66:6:66:11 | Test01 | Usage | test.cpp:120:13:120:23 | sizeof(int) | sizeof | +| test.cpp:120:6:120:24 | sizeof() | $@: $@ of $@ inside sizeof. | test.cpp:120:6:120:24 | sizeof() | sizeof | test.cpp:66:6:66:11 | Test01 | Usage | test.cpp:120:13:120:23 | sizeof(int) | sizeof | +| test.cpp:121:6:121:18 | sizeof() | $@: $@ of $@ inside sizeof. | test.cpp:121:6:121:18 | sizeof() | binary operator | test2.cpp:66:6:66:11 | Test01 | Usage | test.cpp:121:13:121:17 | ... + ... | binary operator | +| test.cpp:121:6:121:18 | sizeof() | $@: $@ of $@ inside sizeof. | test.cpp:121:6:121:18 | sizeof() | binary operator | test.cpp:66:6:66:11 | Test01 | Usage | test.cpp:121:13:121:17 | ... + ... | binary operator | diff --git a/cpp/ql/test/query-tests/Microsoft/Likely Bugs/SizeOfMisuse/ArgumentIsSizeofOrOperation.qlref b/cpp/ql/test/query-tests/Microsoft/Likely Bugs/SizeOfMisuse/ArgumentIsSizeofOrOperation.qlref new file mode 100644 index 000000000000..662f83b06cc0 --- /dev/null +++ b/cpp/ql/test/query-tests/Microsoft/Likely Bugs/SizeOfMisuse/ArgumentIsSizeofOrOperation.qlref @@ -0,0 +1 @@ +Microsoft/Likely Bugs/SizeOfMisuse/ArgumentIsSizeofOrOperation.ql \ No newline at end of file diff --git a/cpp/ql/test/query-tests/Microsoft/Likely Bugs/SizeOfMisuse/SizeOfConstIntMacro.expected b/cpp/ql/test/query-tests/Microsoft/Likely Bugs/SizeOfMisuse/SizeOfConstIntMacro.expected new file mode 100644 index 000000000000..bf751cf1e9b6 --- /dev/null +++ b/cpp/ql/test/query-tests/Microsoft/Likely Bugs/SizeOfMisuse/SizeOfConstIntMacro.expected @@ -0,0 +1,24 @@ +| test2.c:72:6:72:42 | sizeof() | $@: sizeof of integer macro $@ will always return the size of the underlying integer type. | test2.c:72:6:72:42 | sizeof() | Test01 | test2.c:46:1:46:48 | #define SOMESTRUCT_ERRNO_THAT_MATTERS 0x8000000d | SOMESTRUCT_ERRNO_THAT_MATTERS | +| test2.c:80:10:80:32 | sizeof() | $@: sizeof of integer macro $@ will always return the size of the underlying integer type. | test2.c:80:10:80:32 | sizeof() | Test01 | test2.c:2:1:2:26 | #define BAD_MACRO_CONST 5l | BAD_MACRO_CONST | +| test2.c:81:6:81:29 | sizeof() | $@: sizeof of integer macro $@ will always return the size of the underlying integer type. | test2.c:81:6:81:29 | sizeof() | Test01 | test2.c:3:1:3:35 | #define BAD_MACRO_CONST2 0x80005001 | BAD_MACRO_CONST2 | +| test2.c:89:7:89:35 | sizeof() | $@: sizeof of integer macro $@ will always return the size of the underlying integer type. | test2.c:89:7:89:35 | sizeof() | Test01 | test2.c:1:1:1:19 | #define PAGESIZE 64 | PAGESIZE | +| test2.c:98:6:98:31 | sizeof() | $@: sizeof of integer macro $@ will always return the size of the underlying integer type. | test2.c:98:6:98:31 | sizeof() | Test01 | test2.c:17:1:17:40 | #define SOME_SIZEOF_MACRO2 (sizeof(int)) | SOME_SIZEOF_MACRO2 | +| test2.c:112:6:112:37 | sizeof() | $@: sizeof of integer macro $@ will always return the size of the underlying integer type. | test2.c:112:6:112:37 | sizeof() | Test01 | test2.c:31:1:31:45 | #define ACE_CONDITION_SIGNATURE2 'xt' | ACE_CONDITION_SIGNATURE2 | +| test2.cpp:75:6:75:42 | sizeof() | $@: sizeof of integer macro $@ will always return the size of the underlying integer type. | test2.cpp:75:6:75:42 | sizeof() | Test01 | test2.cpp:48:1:48:48 | #define SOMESTRUCT_ERRNO_THAT_MATTERS 0x8000000d | SOMESTRUCT_ERRNO_THAT_MATTERS | +| test2.cpp:83:10:83:32 | sizeof() | $@: sizeof of integer macro $@ will always return the size of the underlying integer type. | test2.cpp:83:10:83:32 | sizeof() | Test01 | test2.cpp:2:1:2:26 | #define BAD_MACRO_CONST 5l | BAD_MACRO_CONST | +| test2.cpp:84:6:84:29 | sizeof() | $@: sizeof of integer macro $@ will always return the size of the underlying integer type. | test2.cpp:84:6:84:29 | sizeof() | Test01 | test2.cpp:3:1:3:35 | #define BAD_MACRO_CONST2 0x80005001 | BAD_MACRO_CONST2 | +| test2.cpp:92:7:92:35 | sizeof() | $@: sizeof of integer macro $@ will always return the size of the underlying integer type. | test2.cpp:92:7:92:35 | sizeof() | Test01 | test2.cpp:1:1:1:19 | #define PAGESIZE 64 | PAGESIZE | +| test2.cpp:101:6:101:31 | sizeof() | $@: sizeof of integer macro $@ will always return the size of the underlying integer type. | test2.cpp:101:6:101:31 | sizeof() | Test01 | test2.cpp:17:1:17:40 | #define SOME_SIZEOF_MACRO2 (sizeof(int)) | SOME_SIZEOF_MACRO2 | +| test2.cpp:116:6:116:37 | sizeof() | $@: sizeof of integer macro $@ will always return the size of the underlying integer type. | test2.cpp:116:6:116:37 | sizeof() | Test01 | test2.cpp:32:1:32:45 | #define ACE_CONDITION_SIGNATURE2 'xt' | ACE_CONDITION_SIGNATURE2 | +| test.c:72:6:72:42 | sizeof() | $@: sizeof of integer macro $@ will always return the size of the underlying integer type. | test.c:72:6:72:42 | sizeof() | Test01 | test.c:46:1:46:48 | #define SOMESTRUCT_ERRNO_THAT_MATTERS 0x8000000d | SOMESTRUCT_ERRNO_THAT_MATTERS | +| test.c:80:10:80:32 | sizeof() | $@: sizeof of integer macro $@ will always return the size of the underlying integer type. | test.c:80:10:80:32 | sizeof() | Test01 | test.c:2:1:2:26 | #define BAD_MACRO_CONST 5l | BAD_MACRO_CONST | +| test.c:81:6:81:29 | sizeof() | $@: sizeof of integer macro $@ will always return the size of the underlying integer type. | test.c:81:6:81:29 | sizeof() | Test01 | test.c:3:1:3:35 | #define BAD_MACRO_CONST2 0x80005001 | BAD_MACRO_CONST2 | +| test.c:89:7:89:35 | sizeof() | $@: sizeof of integer macro $@ will always return the size of the underlying integer type. | test.c:89:7:89:35 | sizeof() | Test01 | test.c:1:1:1:19 | #define PAGESIZE 64 | PAGESIZE | +| test.c:98:6:98:31 | sizeof() | $@: sizeof of integer macro $@ will always return the size of the underlying integer type. | test.c:98:6:98:31 | sizeof() | Test01 | test.c:17:1:17:40 | #define SOME_SIZEOF_MACRO2 (sizeof(int)) | SOME_SIZEOF_MACRO2 | +| test.c:112:6:112:37 | sizeof() | $@: sizeof of integer macro $@ will always return the size of the underlying integer type. | test.c:112:6:112:37 | sizeof() | Test01 | test.c:31:1:31:45 | #define ACE_CONDITION_SIGNATURE2 'xt' | ACE_CONDITION_SIGNATURE2 | +| test.cpp:75:6:75:42 | sizeof() | $@: sizeof of integer macro $@ will always return the size of the underlying integer type. | test.cpp:75:6:75:42 | sizeof() | Test01 | test.cpp:48:1:48:48 | #define SOMESTRUCT_ERRNO_THAT_MATTERS 0x8000000d | SOMESTRUCT_ERRNO_THAT_MATTERS | +| test.cpp:83:10:83:32 | sizeof() | $@: sizeof of integer macro $@ will always return the size of the underlying integer type. | test.cpp:83:10:83:32 | sizeof() | Test01 | test.cpp:2:1:2:26 | #define BAD_MACRO_CONST 5l | BAD_MACRO_CONST | +| test.cpp:84:6:84:29 | sizeof() | $@: sizeof of integer macro $@ will always return the size of the underlying integer type. | test.cpp:84:6:84:29 | sizeof() | Test01 | test.cpp:3:1:3:35 | #define BAD_MACRO_CONST2 0x80005001 | BAD_MACRO_CONST2 | +| test.cpp:92:7:92:35 | sizeof() | $@: sizeof of integer macro $@ will always return the size of the underlying integer type. | test.cpp:92:7:92:35 | sizeof() | Test01 | test.cpp:1:1:1:19 | #define PAGESIZE 64 | PAGESIZE | +| test.cpp:101:6:101:31 | sizeof() | $@: sizeof of integer macro $@ will always return the size of the underlying integer type. | test.cpp:101:6:101:31 | sizeof() | Test01 | test.cpp:17:1:17:40 | #define SOME_SIZEOF_MACRO2 (sizeof(int)) | SOME_SIZEOF_MACRO2 | +| test.cpp:116:6:116:37 | sizeof() | $@: sizeof of integer macro $@ will always return the size of the underlying integer type. | test.cpp:116:6:116:37 | sizeof() | Test01 | test.cpp:32:1:32:45 | #define ACE_CONDITION_SIGNATURE2 'xt' | ACE_CONDITION_SIGNATURE2 | diff --git a/cpp/ql/test/query-tests/Microsoft/Likely Bugs/SizeOfMisuse/SizeOfConstIntMacro.qlref b/cpp/ql/test/query-tests/Microsoft/Likely Bugs/SizeOfMisuse/SizeOfConstIntMacro.qlref new file mode 100644 index 000000000000..3804507965c1 --- /dev/null +++ b/cpp/ql/test/query-tests/Microsoft/Likely Bugs/SizeOfMisuse/SizeOfConstIntMacro.qlref @@ -0,0 +1 @@ +Microsoft/Likely Bugs/SizeOfMisuse/SizeOfConstIntMacro.ql \ No newline at end of file diff --git a/cpp/ql/test/query-tests/Microsoft/Likely Bugs/SizeOfMisuse/test.c b/cpp/ql/test/query-tests/Microsoft/Likely Bugs/SizeOfMisuse/test.c new file mode 100644 index 000000000000..b11d0b552053 --- /dev/null +++ b/cpp/ql/test/query-tests/Microsoft/Likely Bugs/SizeOfMisuse/test.c @@ -0,0 +1,118 @@ +#define PAGESIZE 64 +#define BAD_MACRO_CONST 5l +#define BAD_MACRO_CONST2 0x80005001 +#define BAD_MACRO_OP1(VAR) strlen(#VAR) +#define BAD_MACRO_OP2(VAR) sizeof(VAR)/sizeof(int) + +long strlen(const char* x) { return 5; } + +#define ALIGN_UP_BY(length, sizeofType) length * sizeofType +#define ALIGN_UP(length, type) \ + ALIGN_UP_BY(length, sizeof(type)) + +#define SOME_SIZEOF_MACRO (sizeof(int) * 3) +#define SOME_SIZEOF_MACRO_CAST ((char)(sizeof(int) * 3)) + + +#define SOME_SIZEOF_MACRO2 (sizeof(int)) + +typedef unsigned short WCHAR; // wc, 16-bit UNICODE character + +#define UNICODE_NULL1 ((WCHAR)0) + +#define ASCII_NULL ((char)0) + +#define UNICODE_STRING_SIG L"xtra" +#define ASCII_STRING_SIG "xtra" + +#define UNICODE_SIG L'x' + +#define ACE_CONDITION_SIGNATURE1 'xtra' +#define ACE_CONDITION_SIGNATURE2 'xt' + +#define ACE_CONDITION_SIGNATURE3(VAL) #VAL + +#define NULL (void *)0 + +#define EFI_FILEPATH_SEPARATOR_UNICODE L'\\' + +const char* Test() +{ + return "foobar"; +} + +#define FUNCTION_MACRO_OP1 Test() + +#define SOMESTRUCT_ERRNO_THAT_MATTERS 0x8000000d + + +char _RTL_CONSTANT_STRING_type_check(const void* s) { + return ((char*)(s))[0]; +} + +#define RTL_CONSTANT_STRING(s) \ +{ \ + sizeof( s ) - sizeof( (s)[0] ); \ + sizeof( s ) / sizeof(_RTL_CONSTANT_STRING_type_check(s)); \ +} + +typedef struct { + int a; + char b; +} SOMESTRUCT_THAT_MATTERS; + +void Test01() { + + RTL_CONSTANT_STRING("hello"); + + sizeof(NULL); + sizeof(EFI_FILEPATH_SEPARATOR_UNICODE); + + int y = sizeof(SOMESTRUCT_THAT_MATTERS); + y = sizeof(SOMESTRUCT_ERRNO_THAT_MATTERS); // BUG: SizeOfConstIntMacro + + const unsigned short* p = UNICODE_STRING_SIG; + const char* p2 = ASCII_STRING_SIG; + char p3 = 'xtra'; + unsigned short p4 = L'xtra'; + + int a[10]; + int x = sizeof(BAD_MACRO_CONST); //BUG: SizeOfConstIntMacro + x = sizeof(BAD_MACRO_CONST2); //BUG: SizeOfConstIntMacro + + x = sizeof(FUNCTION_MACRO_OP1); // GOOD + + x = sizeof(BAD_MACRO_OP1(a)); //BUG: ArgumentIsFunctionCall (Low Prec) + x = sizeof(BAD_MACRO_OP2(a)); //BUG: ArgumentIsSizeofOrOperation + + x = 0; + x += ALIGN_UP(sizeof(a), PAGESIZE); //BUG: SizeOfConstIntMacro + x += ALIGN_UP_BY(sizeof(a), PAGESIZE); // GOOD + + x = SOME_SIZEOF_MACRO * 3; // GOOD + x = sizeof(SOME_SIZEOF_MACRO) * 3; //BUG: ArgumentIsSizeofOrOperation + + x = sizeof(SOME_SIZEOF_MACRO_CAST) * 3; //BUG: ArgumentIsSizeofOrOperation + + x = SOME_SIZEOF_MACRO2; // GOOD + x = sizeof(SOME_SIZEOF_MACRO2); //BUG: SizeOfConstIntMacro, ArgumentIsSizeofOrOperation + + x = sizeof(a) / sizeof(int); // GOOD + + x = sizeof(UNICODE_NULL1); + + x = sizeof(ASCII_NULL); + + x = sizeof(UNICODE_STRING_SIG); + x = sizeof(ASCII_STRING_SIG); + + x = sizeof(UNICODE_SIG); + + x = sizeof(ACE_CONDITION_SIGNATURE1); // GOOD (special case) + x = sizeof(ACE_CONDITION_SIGNATURE2); // BUG: SizeOfConstIntMacro + + x = sizeof(ACE_CONDITION_SIGNATURE3(xtra)); + + x = sizeof(sizeof(int)); // BUG: ArgumentIsSizeofOrOperation + x = sizeof(3 + 2); // BUg: ArgumentIsSizeofOrOperation +} diff --git a/cpp/ql/test/query-tests/Microsoft/Likely Bugs/SizeOfMisuse/test.cpp b/cpp/ql/test/query-tests/Microsoft/Likely Bugs/SizeOfMisuse/test.cpp new file mode 100644 index 000000000000..d9622d3c0d94 --- /dev/null +++ b/cpp/ql/test/query-tests/Microsoft/Likely Bugs/SizeOfMisuse/test.cpp @@ -0,0 +1,136 @@ +#define PAGESIZE 64 +#define BAD_MACRO_CONST 5l +#define BAD_MACRO_CONST2 0x80005001 +#define BAD_MACRO_OP1(VAR) strlen(#VAR) +#define BAD_MACRO_OP2(VAR) sizeof(VAR)/sizeof(int) + +long strlen(const char* x) { return 5; } + +#define ALIGN_UP_BY(length, sizeofType) length * sizeofType +#define ALIGN_UP(length, type) \ + ALIGN_UP_BY(length, sizeof(type)) + +#define SOME_SIZEOF_MACRO (sizeof(int) * 3) +#define SOME_SIZEOF_MACRO_CAST ((char)(sizeof(int) * 3)) + + +#define SOME_SIZEOF_MACRO2 (sizeof(int)) + +typedef wchar_t WCHAR; // wc, 16-bit UNICODE character + +#define UNICODE_NULL1 ((WCHAR)0) +#define UNICODE_NULL2 ((wchar_t)0) +#define ASCII_NULL ((char)0) + +#define UNICODE_STRING_SIG L"xtra" +#define ASCII_STRING_SIG "xtra" + +#define ASCII_SIG 'x' +#define UNICODE_SIG L'x' + +#define ACE_CONDITION_SIGNATURE1 'xtra' +#define ACE_CONDITION_SIGNATURE2 'xt' + +#define ACE_CONDITION_SIGNATURE3(VAL) #VAL + +#define NULL (void *)0 + +#define EFI_FILEPATH_SEPARATOR_UNICODE L'\\' +#define EFI_FILEPATH_SEPARATOR_ASCII '\\' + +const char* Test() +{ + return "foobar"; +} + +#define FUNCTION_MACRO_OP1 Test() + +#define SOMESTRUCT_ERRNO_THAT_MATTERS 0x8000000d + + +char _RTL_CONSTANT_STRING_type_check(const void* s) { + return ((char*)(s))[0]; +} + +#define RTL_CONSTANT_STRING(s) \ +{ \ + sizeof( s ) - sizeof( (s)[0] ); \ + sizeof( s ) / sizeof(_RTL_CONSTANT_STRING_type_check(s)); \ +} + +typedef struct { + int a; + bool b; +} SOMESTRUCT_THAT_MATTERS; + +void Test01() { + + RTL_CONSTANT_STRING("hello"); + + sizeof(NULL); + sizeof(EFI_FILEPATH_SEPARATOR_UNICODE); + sizeof(EFI_FILEPATH_SEPARATOR_ASCII); + + int y = sizeof(SOMESTRUCT_THAT_MATTERS); + y = sizeof(SOMESTRUCT_ERRNO_THAT_MATTERS); // BUG: SizeOfConstIntMacro + + const wchar_t* p = UNICODE_STRING_SIG; + const char* p2 = ASCII_STRING_SIG; + char p3 = 'xtra'; + wchar_t p4 = L'xtra'; + + int a[10]; + int x = sizeof(BAD_MACRO_CONST); //BUG: SizeOfConstIntMacro + x = sizeof(BAD_MACRO_CONST2); //BUG: SizeOfConstIntMacro + + x = sizeof(FUNCTION_MACRO_OP1); // GOOD + + x = sizeof(BAD_MACRO_OP1(a)); //BUG: ArgumentIsFunctionCall (Low Prec) + x = sizeof(BAD_MACRO_OP2(a)); //BUG: ArgumentIsSizeofOrOperation + + x = 0; + x += ALIGN_UP(sizeof(a), PAGESIZE); //BUG: SizeOfConstIntMacro + x += ALIGN_UP_BY(sizeof(a), PAGESIZE); // GOOD + + x = SOME_SIZEOF_MACRO * 3; // GOOD + x = sizeof(SOME_SIZEOF_MACRO) * 3; //BUG: ArgumentIsSizeofOrOperation + + x = sizeof(SOME_SIZEOF_MACRO_CAST) * 3; //BUG: ArgumentIsSizeofOrOperation + + x = SOME_SIZEOF_MACRO2; // GOOD + x = sizeof(SOME_SIZEOF_MACRO2); //BUG: SizeOfConstIntMacro, ArgumentIsSizeofOrOperation + + x = sizeof(a) / sizeof(int); // GOOD + + x = sizeof(UNICODE_NULL1); + x = sizeof(UNICODE_NULL2); + x = sizeof(ASCII_NULL); + + x = sizeof(UNICODE_STRING_SIG); + x = sizeof(ASCII_STRING_SIG); + + x = sizeof(ASCII_SIG); + x = sizeof(UNICODE_SIG); + + x = sizeof(ACE_CONDITION_SIGNATURE1); // GOOD (special case) + x = sizeof(ACE_CONDITION_SIGNATURE2); // BUG: SizeOfConstIntMacro + + x = sizeof(ACE_CONDITION_SIGNATURE3(xtra)); + + x = sizeof(sizeof(int)); // BUG: ArgumentIsSizeofOrOperation + x = sizeof(3 + 2); // BUg: ArgumentIsSizeofOrOperation +} + +#define WNULL (L'\0') +#define WNULL_SIZE (sizeof(WNULL)) + +#define RKF_PATH_UTIL_STREAM_MARKER ( L':' ) + +#define _T(x) L ## x + +void test02_FalsePositives() +{ + int x = WNULL_SIZE; + x = sizeof(RKF_PATH_UTIL_STREAM_MARKER); + sizeof(_T('\0')); +} \ No newline at end of file diff --git a/cpp/ql/test/query-tests/Microsoft/Likely Bugs/SizeOfMisuse/test2.c b/cpp/ql/test/query-tests/Microsoft/Likely Bugs/SizeOfMisuse/test2.c new file mode 100644 index 000000000000..b11d0b552053 --- /dev/null +++ b/cpp/ql/test/query-tests/Microsoft/Likely Bugs/SizeOfMisuse/test2.c @@ -0,0 +1,118 @@ +#define PAGESIZE 64 +#define BAD_MACRO_CONST 5l +#define BAD_MACRO_CONST2 0x80005001 +#define BAD_MACRO_OP1(VAR) strlen(#VAR) +#define BAD_MACRO_OP2(VAR) sizeof(VAR)/sizeof(int) + +long strlen(const char* x) { return 5; } + +#define ALIGN_UP_BY(length, sizeofType) length * sizeofType +#define ALIGN_UP(length, type) \ + ALIGN_UP_BY(length, sizeof(type)) + +#define SOME_SIZEOF_MACRO (sizeof(int) * 3) +#define SOME_SIZEOF_MACRO_CAST ((char)(sizeof(int) * 3)) + + +#define SOME_SIZEOF_MACRO2 (sizeof(int)) + +typedef unsigned short WCHAR; // wc, 16-bit UNICODE character + +#define UNICODE_NULL1 ((WCHAR)0) + +#define ASCII_NULL ((char)0) + +#define UNICODE_STRING_SIG L"xtra" +#define ASCII_STRING_SIG "xtra" + +#define UNICODE_SIG L'x' + +#define ACE_CONDITION_SIGNATURE1 'xtra' +#define ACE_CONDITION_SIGNATURE2 'xt' + +#define ACE_CONDITION_SIGNATURE3(VAL) #VAL + +#define NULL (void *)0 + +#define EFI_FILEPATH_SEPARATOR_UNICODE L'\\' + +const char* Test() +{ + return "foobar"; +} + +#define FUNCTION_MACRO_OP1 Test() + +#define SOMESTRUCT_ERRNO_THAT_MATTERS 0x8000000d + + +char _RTL_CONSTANT_STRING_type_check(const void* s) { + return ((char*)(s))[0]; +} + +#define RTL_CONSTANT_STRING(s) \ +{ \ + sizeof( s ) - sizeof( (s)[0] ); \ + sizeof( s ) / sizeof(_RTL_CONSTANT_STRING_type_check(s)); \ +} + +typedef struct { + int a; + char b; +} SOMESTRUCT_THAT_MATTERS; + +void Test01() { + + RTL_CONSTANT_STRING("hello"); + + sizeof(NULL); + sizeof(EFI_FILEPATH_SEPARATOR_UNICODE); + + int y = sizeof(SOMESTRUCT_THAT_MATTERS); + y = sizeof(SOMESTRUCT_ERRNO_THAT_MATTERS); // BUG: SizeOfConstIntMacro + + const unsigned short* p = UNICODE_STRING_SIG; + const char* p2 = ASCII_STRING_SIG; + char p3 = 'xtra'; + unsigned short p4 = L'xtra'; + + int a[10]; + int x = sizeof(BAD_MACRO_CONST); //BUG: SizeOfConstIntMacro + x = sizeof(BAD_MACRO_CONST2); //BUG: SizeOfConstIntMacro + + x = sizeof(FUNCTION_MACRO_OP1); // GOOD + + x = sizeof(BAD_MACRO_OP1(a)); //BUG: ArgumentIsFunctionCall (Low Prec) + x = sizeof(BAD_MACRO_OP2(a)); //BUG: ArgumentIsSizeofOrOperation + + x = 0; + x += ALIGN_UP(sizeof(a), PAGESIZE); //BUG: SizeOfConstIntMacro + x += ALIGN_UP_BY(sizeof(a), PAGESIZE); // GOOD + + x = SOME_SIZEOF_MACRO * 3; // GOOD + x = sizeof(SOME_SIZEOF_MACRO) * 3; //BUG: ArgumentIsSizeofOrOperation + + x = sizeof(SOME_SIZEOF_MACRO_CAST) * 3; //BUG: ArgumentIsSizeofOrOperation + + x = SOME_SIZEOF_MACRO2; // GOOD + x = sizeof(SOME_SIZEOF_MACRO2); //BUG: SizeOfConstIntMacro, ArgumentIsSizeofOrOperation + + x = sizeof(a) / sizeof(int); // GOOD + + x = sizeof(UNICODE_NULL1); + + x = sizeof(ASCII_NULL); + + x = sizeof(UNICODE_STRING_SIG); + x = sizeof(ASCII_STRING_SIG); + + x = sizeof(UNICODE_SIG); + + x = sizeof(ACE_CONDITION_SIGNATURE1); // GOOD (special case) + x = sizeof(ACE_CONDITION_SIGNATURE2); // BUG: SizeOfConstIntMacro + + x = sizeof(ACE_CONDITION_SIGNATURE3(xtra)); + + x = sizeof(sizeof(int)); // BUG: ArgumentIsSizeofOrOperation + x = sizeof(3 + 2); // BUg: ArgumentIsSizeofOrOperation +} diff --git a/cpp/ql/test/query-tests/Microsoft/Likely Bugs/SizeOfMisuse/test2.cpp b/cpp/ql/test/query-tests/Microsoft/Likely Bugs/SizeOfMisuse/test2.cpp new file mode 100644 index 000000000000..d9622d3c0d94 --- /dev/null +++ b/cpp/ql/test/query-tests/Microsoft/Likely Bugs/SizeOfMisuse/test2.cpp @@ -0,0 +1,136 @@ +#define PAGESIZE 64 +#define BAD_MACRO_CONST 5l +#define BAD_MACRO_CONST2 0x80005001 +#define BAD_MACRO_OP1(VAR) strlen(#VAR) +#define BAD_MACRO_OP2(VAR) sizeof(VAR)/sizeof(int) + +long strlen(const char* x) { return 5; } + +#define ALIGN_UP_BY(length, sizeofType) length * sizeofType +#define ALIGN_UP(length, type) \ + ALIGN_UP_BY(length, sizeof(type)) + +#define SOME_SIZEOF_MACRO (sizeof(int) * 3) +#define SOME_SIZEOF_MACRO_CAST ((char)(sizeof(int) * 3)) + + +#define SOME_SIZEOF_MACRO2 (sizeof(int)) + +typedef wchar_t WCHAR; // wc, 16-bit UNICODE character + +#define UNICODE_NULL1 ((WCHAR)0) +#define UNICODE_NULL2 ((wchar_t)0) +#define ASCII_NULL ((char)0) + +#define UNICODE_STRING_SIG L"xtra" +#define ASCII_STRING_SIG "xtra" + +#define ASCII_SIG 'x' +#define UNICODE_SIG L'x' + +#define ACE_CONDITION_SIGNATURE1 'xtra' +#define ACE_CONDITION_SIGNATURE2 'xt' + +#define ACE_CONDITION_SIGNATURE3(VAL) #VAL + +#define NULL (void *)0 + +#define EFI_FILEPATH_SEPARATOR_UNICODE L'\\' +#define EFI_FILEPATH_SEPARATOR_ASCII '\\' + +const char* Test() +{ + return "foobar"; +} + +#define FUNCTION_MACRO_OP1 Test() + +#define SOMESTRUCT_ERRNO_THAT_MATTERS 0x8000000d + + +char _RTL_CONSTANT_STRING_type_check(const void* s) { + return ((char*)(s))[0]; +} + +#define RTL_CONSTANT_STRING(s) \ +{ \ + sizeof( s ) - sizeof( (s)[0] ); \ + sizeof( s ) / sizeof(_RTL_CONSTANT_STRING_type_check(s)); \ +} + +typedef struct { + int a; + bool b; +} SOMESTRUCT_THAT_MATTERS; + +void Test01() { + + RTL_CONSTANT_STRING("hello"); + + sizeof(NULL); + sizeof(EFI_FILEPATH_SEPARATOR_UNICODE); + sizeof(EFI_FILEPATH_SEPARATOR_ASCII); + + int y = sizeof(SOMESTRUCT_THAT_MATTERS); + y = sizeof(SOMESTRUCT_ERRNO_THAT_MATTERS); // BUG: SizeOfConstIntMacro + + const wchar_t* p = UNICODE_STRING_SIG; + const char* p2 = ASCII_STRING_SIG; + char p3 = 'xtra'; + wchar_t p4 = L'xtra'; + + int a[10]; + int x = sizeof(BAD_MACRO_CONST); //BUG: SizeOfConstIntMacro + x = sizeof(BAD_MACRO_CONST2); //BUG: SizeOfConstIntMacro + + x = sizeof(FUNCTION_MACRO_OP1); // GOOD + + x = sizeof(BAD_MACRO_OP1(a)); //BUG: ArgumentIsFunctionCall (Low Prec) + x = sizeof(BAD_MACRO_OP2(a)); //BUG: ArgumentIsSizeofOrOperation + + x = 0; + x += ALIGN_UP(sizeof(a), PAGESIZE); //BUG: SizeOfConstIntMacro + x += ALIGN_UP_BY(sizeof(a), PAGESIZE); // GOOD + + x = SOME_SIZEOF_MACRO * 3; // GOOD + x = sizeof(SOME_SIZEOF_MACRO) * 3; //BUG: ArgumentIsSizeofOrOperation + + x = sizeof(SOME_SIZEOF_MACRO_CAST) * 3; //BUG: ArgumentIsSizeofOrOperation + + x = SOME_SIZEOF_MACRO2; // GOOD + x = sizeof(SOME_SIZEOF_MACRO2); //BUG: SizeOfConstIntMacro, ArgumentIsSizeofOrOperation + + x = sizeof(a) / sizeof(int); // GOOD + + x = sizeof(UNICODE_NULL1); + x = sizeof(UNICODE_NULL2); + x = sizeof(ASCII_NULL); + + x = sizeof(UNICODE_STRING_SIG); + x = sizeof(ASCII_STRING_SIG); + + x = sizeof(ASCII_SIG); + x = sizeof(UNICODE_SIG); + + x = sizeof(ACE_CONDITION_SIGNATURE1); // GOOD (special case) + x = sizeof(ACE_CONDITION_SIGNATURE2); // BUG: SizeOfConstIntMacro + + x = sizeof(ACE_CONDITION_SIGNATURE3(xtra)); + + x = sizeof(sizeof(int)); // BUG: ArgumentIsSizeofOrOperation + x = sizeof(3 + 2); // BUg: ArgumentIsSizeofOrOperation +} + +#define WNULL (L'\0') +#define WNULL_SIZE (sizeof(WNULL)) + +#define RKF_PATH_UTIL_STREAM_MARKER ( L':' ) + +#define _T(x) L ## x + +void test02_FalsePositives() +{ + int x = WNULL_SIZE; + x = sizeof(RKF_PATH_UTIL_STREAM_MARKER); + sizeof(_T('\0')); +} \ No newline at end of file diff --git a/cpp/ql/test/query-tests/Microsoft/Security/Cryptography/BannedEncryption/CapiAndCng/Test.cpp b/cpp/ql/test/query-tests/Microsoft/Security/Cryptography/BannedEncryption/CapiAndCng/Test.cpp new file mode 100644 index 000000000000..01c4a8b7e800 --- /dev/null +++ b/cpp/ql/test/query-tests/Microsoft/Security/Cryptography/BannedEncryption/CapiAndCng/Test.cpp @@ -0,0 +1,205 @@ +#define CONST const + +typedef unsigned long DWORD; +typedef int BOOL; +typedef unsigned char BYTE; +typedef unsigned long ULONG_PTR; +typedef unsigned long *PULONG_PTR; +typedef wchar_t WCHAR; // wc, 16-bit UNICODE character +typedef void *PVOID; +typedef CONST WCHAR *LPCWSTR, *PCWSTR; +typedef PVOID BCRYPT_ALG_HANDLE; +typedef long LONG; +typedef unsigned long ULONG; +typedef ULONG *PULONG; +typedef LONG NTSTATUS; +typedef ULONG_PTR HCRYPTHASH; +typedef ULONG_PTR HCRYPTPROV; +typedef ULONG_PTR HCRYPTKEY; +typedef ULONG_PTR HCRYPTHASH; +typedef unsigned int ALG_ID; + +// algorithm identifier definitions +#define ALG_CLASS_DATA_ENCRYPT (3 << 13) +#define ALG_TYPE_ANY (0) +#define ALG_TYPE_BLOCK (3 << 9) +#define ALG_TYPE_STREAM (4 << 9) +#define ALG_TYPE_THIRDPARTY (8 << 9) +#define ALG_SID_THIRDPARTY_ANY (0) + +#define ALG_SID_DES 1 +#define ALG_SID_3DES 3 +#define ALG_SID_DESX 4 +#define ALG_SID_IDEA 5 +#define ALG_SID_CAST 6 +#define ALG_SID_SAFERSK64 7 +#define ALG_SID_SAFERSK128 8 +#define ALG_SID_3DES_112 9 +#define ALG_SID_CYLINK_MEK 12 +#define ALG_SID_RC5 13 +#define ALG_SID_AES_128 14 +#define ALG_SID_AES_192 15 +#define ALG_SID_AES_256 16 +#define ALG_SID_AES 17 +// Fortezza sub-ids +#define ALG_SID_SKIPJACK 10 +#define ALG_SID_TEK 11 +// RC2 sub-ids +#define ALG_SID_RC2 2 +// Stream cipher sub-ids +#define ALG_SID_RC4 1 +#define ALG_SID_SEAL 2 + +// CAPI encryption algorithm definitions +#define CALG_DES (ALG_CLASS_DATA_ENCRYPT|ALG_TYPE_BLOCK|ALG_SID_DES) +#define CALG_3DES_112 (ALG_CLASS_DATA_ENCRYPT|ALG_TYPE_BLOCK|ALG_SID_3DES_112) +#define CALG_3DES (ALG_CLASS_DATA_ENCRYPT|ALG_TYPE_BLOCK|ALG_SID_3DES) +#define CALG_DESX (ALG_CLASS_DATA_ENCRYPT|ALG_TYPE_BLOCK|ALG_SID_DESX) +#define CALG_RC2 (ALG_CLASS_DATA_ENCRYPT|ALG_TYPE_BLOCK|ALG_SID_RC2) +#define CALG_RC4 (ALG_CLASS_DATA_ENCRYPT|ALG_TYPE_STREAM|ALG_SID_RC4) +#define CALG_SEAL (ALG_CLASS_DATA_ENCRYPT|ALG_TYPE_STREAM|ALG_SID_SEAL) +#define CALG_SKIPJACK (ALG_CLASS_DATA_ENCRYPT|ALG_TYPE_BLOCK|ALG_SID_SKIPJACK) +#define CALG_TEK (ALG_CLASS_DATA_ENCRYPT|ALG_TYPE_BLOCK|ALG_SID_TEK) +#define CALG_CYLINK_MEK (ALG_CLASS_DATA_ENCRYPT|ALG_TYPE_BLOCK|ALG_SID_CYLINK_MEK) // Deprecated. Do not use +#define CALG_RC5 (ALG_CLASS_DATA_ENCRYPT|ALG_TYPE_BLOCK|ALG_SID_RC5) +#define CALG_AES_128 (ALG_CLASS_DATA_ENCRYPT|ALG_TYPE_BLOCK|ALG_SID_AES_128) +#define CALG_AES_192 (ALG_CLASS_DATA_ENCRYPT|ALG_TYPE_BLOCK|ALG_SID_AES_192) +#define CALG_AES_256 (ALG_CLASS_DATA_ENCRYPT|ALG_TYPE_BLOCK|ALG_SID_AES_256) +#define CALG_AES (ALG_CLASS_DATA_ENCRYPT|ALG_TYPE_BLOCK|ALG_SID_AES) +#define CALG_THIRDPARTY_CIPHER (ALG_CLASS_DATA_ENCRYPT | ALG_TYPE_THIRDPARTY | ALG_SID_THIRDPARTY_ANY) + + +#define BCRYPT_RC2_ALGORITHM L"RC2" +#define BCRYPT_RC4_ALGORITHM L"RC4" +#define BCRYPT_AES_ALGORITHM L"AES" +#define BCRYPT_DES_ALGORITHM L"DES" +#define BCRYPT_DESX_ALGORITHM L"DESX" +#define BCRYPT_3DES_ALGORITHM L"3DES" +#define BCRYPT_3DES_112_ALGORITHM L"3DES_112" +#define BCRYPT_AES_GMAC_ALGORITHM L"AES-GMAC" +#define BCRYPT_AES_CMAC_ALGORITHM L"AES-CMAC" +#define BCRYPT_XTS_AES_ALGORITHM L"XTS-AES" + +BOOL +CryptGenKey( + HCRYPTPROV hProv, + ALG_ID Algid, + DWORD dwFlags, + HCRYPTKEY *phKey) +{ + return 0; +} + +BOOL +CryptDeriveKey( + HCRYPTPROV hProv, + ALG_ID Algid, + HCRYPTHASH hBaseData, + DWORD dwFlags, + HCRYPTKEY *phKey) +{ + return 0; +} + +void +DummyFunction( + LPCWSTR pszAlgId, + ALG_ID Algid) +{} + +NTSTATUS +BCryptOpenAlgorithmProvider( + BCRYPT_ALG_HANDLE *phAlgorithm, + LPCWSTR pszAlgId, + LPCWSTR pszImplementation, + ULONG dwFlags) +{ + return 0; +} + +// Macro testing +#define MACRO_INVOCATION_CRYPTGENKEY CryptGenKey(0, CALG_RC4, 0, 0); +#define MACRO_INVOCATION_CRYPTDERIVEKEY CryptDeriveKey(0, CALG_CYLINK_MEK, 0, 0, 0); +#define MACRO_INVOCATION_CNG BCryptOpenAlgorithmProvider(0, BCRYPT_3DES_112_ALGORITHM, 0, 0); + +int main() +{ + //////////////////////////// + // CAPI Test section + // Should fire an event + CryptGenKey(0, CALG_DES, 0, 0); + CryptGenKey(0, CALG_3DES_112, 0, 0); + CryptGenKey(0, CALG_3DES, 0, 0); + CryptGenKey(0, CALG_DESX, 0, 0); + CryptGenKey(0, CALG_RC2, 0, 0); + CryptGenKey(0, CALG_RC4, 0, 0); + CryptGenKey(0, CALG_SEAL, 0, 0); + CryptGenKey(0, CALG_SKIPJACK, 0, 0); + CryptGenKey(0, CALG_TEK, 0, 0); + CryptGenKey(0, CALG_CYLINK_MEK, 0, 0); + CryptGenKey(0, CALG_RC5, 0, 0); + CryptGenKey(0, CALG_THIRDPARTY_CIPHER, 0, 0); + CryptGenKey(0, ALG_CLASS_DATA_ENCRYPT, 0, 0); + CryptGenKey(0, ALG_CLASS_DATA_ENCRYPT | ALG_TYPE_BLOCK, 0, 0); + CryptGenKey(0, ALG_CLASS_DATA_ENCRYPT | ALG_TYPE_STREAM, 0, 0); + // Verifying that all stream ciphers are flagged + CryptGenKey(0, ALG_CLASS_DATA_ENCRYPT | ALG_TYPE_STREAM | ALG_SID_AES, 0, 0); + // Verifying that invocations through a macro are flagged + MACRO_INVOCATION_CRYPTGENKEY + // Numeric representation + CryptGenKey(0, 0x6609, 0, 0); + + CryptDeriveKey(0, CALG_DES, 0, 0, 0); + CryptDeriveKey(0, CALG_3DES_112, 0, 0, 0); + CryptDeriveKey(0, CALG_3DES, 0, 0, 0); + CryptDeriveKey(0, CALG_DESX, 0, 0, 0); + CryptDeriveKey(0, CALG_RC2, 0, 0, 0); + CryptDeriveKey(0, CALG_RC4, 0, 0, 0); + CryptDeriveKey(0, CALG_SEAL, 0, 0, 0); + CryptDeriveKey(0, CALG_SKIPJACK, 0, 0, 0); + CryptDeriveKey(0, CALG_TEK, 0, 0, 0); + CryptDeriveKey(0, CALG_CYLINK_MEK, 0, 0, 0); + CryptDeriveKey(0, CALG_RC5, 0, 0, 0); + CryptDeriveKey(0, CALG_THIRDPARTY_CIPHER, 0, 0, 0); + CryptDeriveKey(0, ALG_CLASS_DATA_ENCRYPT, 0, 0, 0); + CryptDeriveKey(0, ALG_CLASS_DATA_ENCRYPT | ALG_TYPE_BLOCK, 0, 0, 0); + CryptDeriveKey(0, ALG_CLASS_DATA_ENCRYPT | ALG_TYPE_STREAM, 0, 0, 0); + // Verifying that all stream ciphers are flagged + CryptDeriveKey(0, ALG_CLASS_DATA_ENCRYPT | ALG_TYPE_STREAM | ALG_SID_AES, 0, 0, 0); + // Verifying that invocations through a macro are flagged + MACRO_INVOCATION_CRYPTDERIVEKEY + // Numeric representation + CryptDeriveKey(0, 0x6609, 0, 0, 0); + + // Should not fire an event + CryptGenKey(0, CALG_AES_128, 0, 0); + CryptGenKey(0, CALG_AES_192, 0, 0); + CryptGenKey(0, CALG_AES_256, 0, 0); + CryptGenKey(0, CALG_AES, 0, 0); + CryptDeriveKey(0, CALG_AES_128, 0, 0, 0); + CryptDeriveKey(0, CALG_AES_192, 0, 0, 0); + CryptDeriveKey(0, CALG_AES_256, 0, 0, 0); + CryptDeriveKey(0, CALG_AES, 0, 0, 0); + if (CALG_RC5 > 0) + { + DummyFunction(0, CALG_SKIPJACK); + } + + ///////////////////////////// + // CNG Test section + // Should fire an event + BCryptOpenAlgorithmProvider(0, BCRYPT_RC2_ALGORITHM, 0, 0); + BCryptOpenAlgorithmProvider(0, BCRYPT_RC4_ALGORITHM, 0, 0); + BCryptOpenAlgorithmProvider(0, BCRYPT_DES_ALGORITHM, 0, 0); + BCryptOpenAlgorithmProvider(0, BCRYPT_DESX_ALGORITHM, 0, 0); + BCryptOpenAlgorithmProvider(0, BCRYPT_3DES_ALGORITHM, 0, 0); + BCryptOpenAlgorithmProvider(0, BCRYPT_3DES_112_ALGORITHM, 0, 0); + BCryptOpenAlgorithmProvider(0, BCRYPT_AES_GMAC_ALGORITHM, 0, 0); + BCryptOpenAlgorithmProvider(0, BCRYPT_AES_CMAC_ALGORITHM, 0, 0); + BCryptOpenAlgorithmProvider(0, L"3DES", 0, 0); + MACRO_INVOCATION_CNG + + // Should not fire an event + BCryptOpenAlgorithmProvider(0, BCRYPT_AES_ALGORITHM, 0, 0); + BCryptOpenAlgorithmProvider(0, BCRYPT_XTS_AES_ALGORITHM, 0, 0); +} \ No newline at end of file diff --git a/cpp/ql/test/query-tests/Microsoft/Security/Cryptography/BannedEncryption/CapiAndCng/WeakEncryption.expected b/cpp/ql/test/query-tests/Microsoft/Security/Cryptography/BannedEncryption/CapiAndCng/WeakEncryption.expected new file mode 100644 index 000000000000..bb9b8c65c83c --- /dev/null +++ b/cpp/ql/test/query-tests/Microsoft/Security/Cryptography/BannedEncryption/CapiAndCng/WeakEncryption.expected @@ -0,0 +1,46 @@ +| Test.cpp:130:17:130:24 | ... \| ... | Call to a cryptographic function with a banned symmetric encryption algorithm: CALG_DES | Test.cpp:130:17:130:24 | ... \| ... | ... \| ... | +| Test.cpp:131:17:131:29 | ... \| ... | Call to a cryptographic function with a banned symmetric encryption algorithm: CALG_3DES_112 | Test.cpp:131:17:131:29 | ... \| ... | ... \| ... | +| Test.cpp:132:17:132:25 | ... \| ... | Call to a cryptographic function with a banned symmetric encryption algorithm: CALG_3DES | Test.cpp:132:17:132:25 | ... \| ... | ... \| ... | +| Test.cpp:133:17:133:25 | ... \| ... | Call to a cryptographic function with a banned symmetric encryption algorithm: CALG_DESX | Test.cpp:133:17:133:25 | ... \| ... | ... \| ... | +| Test.cpp:134:17:134:24 | ... \| ... | Call to a cryptographic function with a banned symmetric encryption algorithm: CALG_RC2 | Test.cpp:134:17:134:24 | ... \| ... | ... \| ... | +| Test.cpp:135:17:135:24 | ... \| ... | Call to a cryptographic function with a banned symmetric encryption algorithm: CALG_RC4 | Test.cpp:135:17:135:24 | ... \| ... | ... \| ... | +| Test.cpp:136:17:136:25 | ... \| ... | Call to a cryptographic function with a banned symmetric encryption algorithm: CALG_SEAL | Test.cpp:136:17:136:25 | ... \| ... | ... \| ... | +| Test.cpp:137:17:137:29 | ... \| ... | Call to a cryptographic function with a banned symmetric encryption algorithm: CALG_SKIPJACK | Test.cpp:137:17:137:29 | ... \| ... | ... \| ... | +| Test.cpp:138:17:138:24 | ... \| ... | Call to a cryptographic function with a banned symmetric encryption algorithm: CALG_TEK | Test.cpp:138:17:138:24 | ... \| ... | ... \| ... | +| Test.cpp:139:17:139:31 | ... \| ... | Call to a cryptographic function with a banned symmetric encryption algorithm: CALG_CYLINK_MEK | Test.cpp:139:17:139:31 | ... \| ... | ... \| ... | +| Test.cpp:140:17:140:24 | ... \| ... | Call to a cryptographic function with a banned symmetric encryption algorithm: CALG_RC5 | Test.cpp:140:17:140:24 | ... \| ... | ... \| ... | +| Test.cpp:141:17:141:38 | ... \| ... | Call to a cryptographic function with a banned symmetric encryption algorithm: CALG_THIRDPARTY_CIPHER | Test.cpp:141:17:141:38 | ... \| ... | ... \| ... | +| Test.cpp:142:17:142:38 | ... << ... | Call to a cryptographic function with a banned symmetric encryption algorithm: ALG_CLASS_DATA_ENCRYPT | Test.cpp:142:17:142:38 | ... << ... | ... << ... | +| Test.cpp:143:17:143:55 | ... \| ... | Call to a cryptographic function with a banned symmetric encryption algorithm: 26112 | Test.cpp:143:17:143:55 | ... \| ... | ... \| ... | +| Test.cpp:144:17:144:56 | ... \| ... | Call to a cryptographic function with a banned symmetric encryption algorithm: 26624 | Test.cpp:144:17:144:56 | ... \| ... | ... \| ... | +| Test.cpp:146:17:146:70 | ... \| ... | Call to a cryptographic function with a banned symmetric encryption algorithm: 26641 | Test.cpp:146:17:146:70 | ... \| ... | ... \| ... | +| Test.cpp:148:2:148:29 | ... \| ... | Call to a cryptographic function with a banned symmetric encryption algorithm: 26625 | Test.cpp:148:2:148:29 | ... \| ... | ... \| ... | +| Test.cpp:150:17:150:22 | 26121 | Call to a cryptographic function with a banned symmetric encryption algorithm: 0x6609 | Test.cpp:150:17:150:22 | 26121 | 26121 | +| Test.cpp:152:20:152:27 | ... \| ... | Call to a cryptographic function with a banned symmetric encryption algorithm: CALG_DES | Test.cpp:152:20:152:27 | ... \| ... | ... \| ... | +| Test.cpp:153:20:153:32 | ... \| ... | Call to a cryptographic function with a banned symmetric encryption algorithm: CALG_3DES_112 | Test.cpp:153:20:153:32 | ... \| ... | ... \| ... | +| Test.cpp:154:20:154:28 | ... \| ... | Call to a cryptographic function with a banned symmetric encryption algorithm: CALG_3DES | Test.cpp:154:20:154:28 | ... \| ... | ... \| ... | +| Test.cpp:155:20:155:28 | ... \| ... | Call to a cryptographic function with a banned symmetric encryption algorithm: CALG_DESX | Test.cpp:155:20:155:28 | ... \| ... | ... \| ... | +| Test.cpp:156:20:156:27 | ... \| ... | Call to a cryptographic function with a banned symmetric encryption algorithm: CALG_RC2 | Test.cpp:156:20:156:27 | ... \| ... | ... \| ... | +| Test.cpp:157:20:157:27 | ... \| ... | Call to a cryptographic function with a banned symmetric encryption algorithm: CALG_RC4 | Test.cpp:157:20:157:27 | ... \| ... | ... \| ... | +| Test.cpp:158:20:158:28 | ... \| ... | Call to a cryptographic function with a banned symmetric encryption algorithm: CALG_SEAL | Test.cpp:158:20:158:28 | ... \| ... | ... \| ... | +| Test.cpp:159:20:159:32 | ... \| ... | Call to a cryptographic function with a banned symmetric encryption algorithm: CALG_SKIPJACK | Test.cpp:159:20:159:32 | ... \| ... | ... \| ... | +| Test.cpp:160:20:160:27 | ... \| ... | Call to a cryptographic function with a banned symmetric encryption algorithm: CALG_TEK | Test.cpp:160:20:160:27 | ... \| ... | ... \| ... | +| Test.cpp:161:20:161:34 | ... \| ... | Call to a cryptographic function with a banned symmetric encryption algorithm: CALG_CYLINK_MEK | Test.cpp:161:20:161:34 | ... \| ... | ... \| ... | +| Test.cpp:162:20:162:27 | ... \| ... | Call to a cryptographic function with a banned symmetric encryption algorithm: CALG_RC5 | Test.cpp:162:20:162:27 | ... \| ... | ... \| ... | +| Test.cpp:163:20:163:41 | ... \| ... | Call to a cryptographic function with a banned symmetric encryption algorithm: CALG_THIRDPARTY_CIPHER | Test.cpp:163:20:163:41 | ... \| ... | ... \| ... | +| Test.cpp:164:20:164:41 | ... << ... | Call to a cryptographic function with a banned symmetric encryption algorithm: ALG_CLASS_DATA_ENCRYPT | Test.cpp:164:20:164:41 | ... << ... | ... << ... | +| Test.cpp:165:20:165:58 | ... \| ... | Call to a cryptographic function with a banned symmetric encryption algorithm: 26112 | Test.cpp:165:20:165:58 | ... \| ... | ... \| ... | +| Test.cpp:166:20:166:59 | ... \| ... | Call to a cryptographic function with a banned symmetric encryption algorithm: 26624 | Test.cpp:166:20:166:59 | ... \| ... | ... \| ... | +| Test.cpp:168:20:168:73 | ... \| ... | Call to a cryptographic function with a banned symmetric encryption algorithm: 26641 | Test.cpp:168:20:168:73 | ... \| ... | ... \| ... | +| Test.cpp:170:2:170:32 | ... \| ... | Call to a cryptographic function with a banned symmetric encryption algorithm: 26124 | Test.cpp:170:2:170:32 | ... \| ... | ... \| ... | +| Test.cpp:172:20:172:25 | 26121 | Call to a cryptographic function with a banned symmetric encryption algorithm: 0x6609 | Test.cpp:172:20:172:25 | 26121 | 26121 | +| Test.cpp:191:33:191:52 | RC2 | Call to a cryptographic function with a banned symmetric encryption algorithm: BCRYPT_RC2_ALGORITHM | Test.cpp:191:33:191:52 | RC2 | RC2 | +| Test.cpp:192:33:192:52 | RC4 | Call to a cryptographic function with a banned symmetric encryption algorithm: BCRYPT_RC4_ALGORITHM | Test.cpp:192:33:192:52 | RC4 | RC4 | +| Test.cpp:193:33:193:52 | DES | Call to a cryptographic function with a banned symmetric encryption algorithm: BCRYPT_DES_ALGORITHM | Test.cpp:193:33:193:52 | DES | DES | +| Test.cpp:194:33:194:53 | DESX | Call to a cryptographic function with a banned symmetric encryption algorithm: BCRYPT_DESX_ALGORITHM | Test.cpp:194:33:194:53 | DESX | DESX | +| Test.cpp:195:33:195:53 | 3DES | Call to a cryptographic function with a banned symmetric encryption algorithm: BCRYPT_3DES_ALGORITHM | Test.cpp:195:33:195:53 | 3DES | 3DES | +| Test.cpp:196:33:196:57 | 3DES_112 | Call to a cryptographic function with a banned symmetric encryption algorithm: BCRYPT_3DES_112_ALGORITHM | Test.cpp:196:33:196:57 | 3DES_112 | 3DES_112 | +| Test.cpp:197:33:197:57 | AES-GMAC | Call to a cryptographic function with a banned symmetric encryption algorithm: BCRYPT_AES_GMAC_ALGORITHM | Test.cpp:197:33:197:57 | AES-GMAC | AES-GMAC | +| Test.cpp:198:33:198:57 | AES-CMAC | Call to a cryptographic function with a banned symmetric encryption algorithm: BCRYPT_AES_CMAC_ALGORITHM | Test.cpp:198:33:198:57 | AES-CMAC | AES-CMAC | +| Test.cpp:199:33:199:39 | 3DES | Call to a cryptographic function with a banned symmetric encryption algorithm: L"3DES" | Test.cpp:199:33:199:39 | 3DES | 3DES | +| Test.cpp:200:2:200:21 | 3DES_112 | Call to a cryptographic function with a banned symmetric encryption algorithm: 3DES_112 | Test.cpp:200:2:200:21 | 3DES_112 | 3DES_112 | diff --git a/cpp/ql/test/query-tests/Microsoft/Security/Cryptography/BannedEncryption/CapiAndCng/WeakEncryption.qlref b/cpp/ql/test/query-tests/Microsoft/Security/Cryptography/BannedEncryption/CapiAndCng/WeakEncryption.qlref new file mode 100644 index 000000000000..cfdff69c3171 --- /dev/null +++ b/cpp/ql/test/query-tests/Microsoft/Security/Cryptography/BannedEncryption/CapiAndCng/WeakEncryption.qlref @@ -0,0 +1 @@ +Microsoft/Security/Cryptography/BannedEncryption.ql \ No newline at end of file diff --git a/cpp/ql/test/query-tests/Microsoft/Security/Cryptography/BannedEncryption/modeled_apis/Test.cpp b/cpp/ql/test/query-tests/Microsoft/Security/Cryptography/BannedEncryption/modeled_apis/Test.cpp new file mode 100644 index 000000000000..f4c58d6b9ea9 --- /dev/null +++ b/cpp/ql/test/query-tests/Microsoft/Security/Cryptography/BannedEncryption/modeled_apis/Test.cpp @@ -0,0 +1,191 @@ +#include "./openssl/other.h" + +// Other RC4 +void RC4() +{ + int myRc4 = 0; +} + +void* malloc(int size); + +#define MACRO_RC4 RC4(0, 0, 0, 0); +#define NULL 0 + +void func_calls() +{ + // Should not be flagged + AES_encrypt(0, 0, 0); + AES_cbc_encrypt(0, 0, 0, 0, 0, 0); + + // OK Encryption but bad mode + AES_ecb_encrypt(0, 0, 0, 0); + AES_cfb128_encrypt(0, 0, 0, 0, 0, 0, 0); + AES_cfb1_encrypt(0, 0, 0, 0, 0, 0, 0); + AES_cfb8_encrypt(0, 0, 0, 0, 0, 0, 0); + AES_ofb128_encrypt(0, 0, 0, 0, 0, 0); + AES_ige_encrypt(0, 0, 0, 0, 0, 0); + AES_bi_ige_encrypt(0, 0, 0, 0, 0, 0, 0); + + // Everything else should be flagged as bad encryption + MACRO_RC4 + BF_encrypt(0,0); + BF_ecb_encrypt(0,0,0,0); + BF_cbc_encrypt(0, 0, 0, 0, 0, 0); + BF_cfb64_encrypt(0, 0, 0, 0, 0, 0,0); + BF_ofb64_encrypt(0, 0, 0, 0, 0, 0); + Camellia_encrypt(0,0,0); + Camellia_ecb_encrypt(0, 0, 0, 0); + Camellia_cbc_encrypt(0, 0, 0, 0, 0, 0); + Camellia_cfb128_encrypt(0, 0, 0, 0, 0, 0, 0); + Camellia_cfb1_encrypt(0, 0, 0, 0, 0, 0, 0); + Camellia_cfb8_encrypt(0, 0, 0, 0, 0, 0,0); + Camellia_ofb128_encrypt(0, 0, 0, 0, 0, 0); + Camellia_ctr128_encrypt(0, 0, 0, 0, 0, 0,0); + DES_ecb3_encrypt(0,0,0,0,0,0); + DES_cbc_encrypt(0, 0, 0, 0, 0, 0); + DES_ncbc_encrypt(0, 0, 0, 0, 0, 0); + DES_xcbc_encrypt(0, 0, 0, 0, 0, 0,0,0); + DES_cfb_encrypt(0, 0, 0, 0, 0, 0,0); + DES_ecb_encrypt(0, 0, 0, 0); + DES_encrypt1(0, 0, 0); + DES_encrypt2(0, 0, 0); + DES_encrypt3(0, 0, 0,0); + DES_ede3_cbc_encrypt(0, 0, 0, 0, 0, 0, 0,0); + DES_ofb64_encrypt(0,0,0,0,0,0); + IDEA_ecb_encrypt(0,0,0); + IDEA_cbc_encrypt(0,0,0,0,0,0); + IDEA_cfb64_encrypt(0, 0, 0, 0, 0, 0,0); + IDEA_ofb64_encrypt(0, 0, 0, 0, 0, 0); + IDEA_encrypt(0, 0); + RC2_ecb_encrypt(0, 0, 0, 0); + RC2_encrypt(0, 0); + RC2_cbc_encrypt(0, 0, 0, 0, 0, 0); + RC2_cfb64_encrypt(0, 0, 0, 0, 0, 0,0); + RC2_ofb64_encrypt(0, 0, 0, 0, 0, 0); + RC5_32_ecb_encrypt(0, 0, 0, 0); + RC5_32_encrypt(0,0); + RC5_32_cbc_encrypt(0, 0, 0, 0, 0, 0); + RC5_32_cfb64_encrypt(0, 0, 0, 0, 0, 0, 0); + RC5_32_ofb64_encrypt(0, 0, 0, 0, 0, 0); + RC4_set_key(0,0,0); + RC4(0, 0, 0, 0); +} + +void non_func_calls(int argc, char **argv) +{ + // GOOD cases: should not be flagged + { + EVP_CIPHER *cipher = NULL; + ASN1_OBJECT *obj = (ASN1_OBJECT *)malloc(sizeof(ASN1_OBJECT)); + + cipher = EVP_CIPHER_fetch(NULL, "aes-256-xts", NULL); + cipher = EVP_get_cipherbyname("aes-128-cbc"); + cipher = EVP_get_cipherbynid(423); //NID 423 is aes-192-cbc + obj->nid = 913; // NID 913 is aes-128-xts + cipher = EVP_get_cipherbyobj(obj); + obj = (ASN1_OBJECT*)malloc(sizeof(ASN1_OBJECT)); + obj->sn = "aes-128-cbc-hmac-sha1"; + cipher = EVP_get_cipherbyobj(obj); + + // Indirect flow through transformative functions (i.e., converting the alg format) + int nid = OBJ_obj2nid(obj); + cipher = EVP_get_cipherbynid(nid); + ASN1_OBJECT *obj_cpy = OBJ_dup(obj); + cipher = EVP_get_cipherbyobj(obj_cpy); + char* name = "THIS STRING WILL BE OVERWRITTEN"; + OBJ_obj2txt(name, 0, obj, 0); + cipher = EVP_get_cipherbyname(name); + nid = OBJ_obj2nid(obj_cpy); + name = OBJ_nid2sn(nid); + ASN1_OBJECT *obj2 = OBJ_txt2obj(name, 0); + cipher = EVP_get_cipherbyobj(obj2); + } + + // Bad Cases: UNKNOWN algorithms + { + EVP_CIPHER *cipher = NULL; + ASN1_OBJECT *obj = (ASN1_OBJECT *)malloc(sizeof(ASN1_OBJECT)); + + cipher = EVP_CIPHER_fetch(NULL, "FOOBAR", NULL); + cipher = EVP_get_cipherbyname("TEST"); + cipher = EVP_get_cipherbynid(2000); + obj = (ASN1_OBJECT *)malloc(sizeof(ASN1_OBJECT)); + obj->nid = 1999; + cipher = EVP_get_cipherbyobj(obj); + obj = (ASN1_OBJECT *)malloc(sizeof(ASN1_OBJECT)); + obj->sn = "Test2"; + cipher = EVP_get_cipherbyobj(obj); + obj = (ASN1_OBJECT *)malloc(sizeof(ASN1_OBJECT)); + obj->sn = argv[0]; // Ignoring the possible overflow + cipher = EVP_get_cipherbyobj(obj); + + cipher = EVP_CIPHER_fetch(NULL, "NULL", NULL); + cipher = EVP_CIPHER_fetch(NULL, "othermailbox", NULL); + + cipher = EVP_get_cipherbynid(0); + + // Indirect flow through transformative functions (i.e., converting the alg format) + // Testing flow with unknown inputs should be sufficient with known bad inputs, + // so only testing with known bad inputs for UNKNOWN for now. + ASN1_OBJECT *obj_cpy = NULL; + ASN1_OBJECT *obj2 = NULL; + obj->nid = 1998; + int nid = OBJ_obj2nid(obj); + cipher = EVP_get_cipherbynid(nid); + obj->nid = 1997; + obj_cpy = OBJ_dup(obj); + cipher = EVP_get_cipherbyobj(obj_cpy); + obj->sn = "NOT AN ALG"; + char* name = "THIS STRING WILL BE OVERWRITTEN"; + OBJ_obj2txt(name, 0, obj, 0); + cipher = EVP_get_cipherbyname(name); + obj->nid = 1996; + obj_cpy = OBJ_dup(obj); + nid = OBJ_obj2nid(obj_cpy); + name = OBJ_nid2sn(nid); + obj2 = OBJ_txt2obj(name, 0); + cipher = EVP_get_cipherbyobj(obj2); + + // Nonsense cases (known algorithms to incorrect sinks) + cipher = EVP_get_cipherbynid(19); // NID 19 is RSA + cipher = EVP_get_cipherbyname("secp160k1"); // An elliptic curve + } + + // Bad Cases: Banned algorithms + { + EVP_CIPHER *cipher = NULL; + ASN1_OBJECT *obj = (ASN1_OBJECT *)malloc(sizeof(ASN1_OBJECT)); + + // banned symmetric ciphers + cipher = EVP_CIPHER_fetch(NULL, "des-ede3", NULL); + cipher = EVP_get_cipherbyname("des-ede3-cbc"); + cipher = EVP_get_cipherbynid(31); // NID 31 is des-cbc + obj = (ASN1_OBJECT *)malloc(sizeof(ASN1_OBJECT)); + obj->nid = 30; // NID 30 is des-cfb + cipher = EVP_get_cipherbyobj(obj); + obj = (ASN1_OBJECT *)malloc(sizeof(ASN1_OBJECT)); + obj->sn = "camellia256"; + cipher = EVP_get_cipherbyobj(obj); + cipher = EVP_CIPHER_fetch(NULL, "rc4", NULL); + cipher = EVP_get_cipherbyname("rc4-40"); + cipher = EVP_get_cipherbynid(5); // NID 5 is rc4 + obj = (ASN1_OBJECT *)malloc(sizeof(ASN1_OBJECT)); + obj->sn = "desx-cbc"; + cipher = EVP_get_cipherbyobj(obj); + cipher = EVP_CIPHER_fetch(NULL, "bf-cbc", NULL); + cipher = EVP_get_cipherbyname("rc2-64-cbc"); + cipher = EVP_get_cipherbynid(1019); // NID 1019 is chacha20 + obj = (ASN1_OBJECT *)malloc(sizeof(ASN1_OBJECT)); + obj->nid = 813; // NID 813 is gost89 + cipher = EVP_get_cipherbyobj(obj); + obj = (ASN1_OBJECT *)malloc(sizeof(ASN1_OBJECT)); + obj->sn = "sm4-cbc"; + cipher = EVP_get_cipherbyobj(obj); + } +} + +int main(int argc, char **argv) +{ + func_calls(); + non_func_calls(argc, argv); +} \ No newline at end of file diff --git a/cpp/ql/test/query-tests/Microsoft/Security/Cryptography/BannedEncryption/modeled_apis/WeakEncryption.expected b/cpp/ql/test/query-tests/Microsoft/Security/Cryptography/BannedEncryption/modeled_apis/WeakEncryption.expected new file mode 100644 index 000000000000..a9165f715dae --- /dev/null +++ b/cpp/ql/test/query-tests/Microsoft/Security/Cryptography/BannedEncryption/modeled_apis/WeakEncryption.expected @@ -0,0 +1,57 @@ +| Test.cpp:30:2:30:10 | call to RC4 | Use of banned symmetric encryption algorithm: RC4. | Test.cpp:30:2:30:10 | call to RC4 | call to RC4 | +| Test.cpp:31:2:31:11 | call to BF_encrypt | Use of banned symmetric encryption algorithm: BF. | Test.cpp:31:2:31:11 | call to BF_encrypt | call to BF_encrypt | +| Test.cpp:32:2:32:15 | call to BF_ecb_encrypt | Use of banned symmetric encryption algorithm: BF. | Test.cpp:32:2:32:15 | call to BF_ecb_encrypt | call to BF_ecb_encrypt | +| Test.cpp:33:2:33:15 | call to BF_cbc_encrypt | Use of banned symmetric encryption algorithm: BF. | Test.cpp:33:2:33:15 | call to BF_cbc_encrypt | call to BF_cbc_encrypt | +| Test.cpp:34:2:34:17 | call to BF_cfb64_encrypt | Use of banned symmetric encryption algorithm: BF. | Test.cpp:34:2:34:17 | call to BF_cfb64_encrypt | call to BF_cfb64_encrypt | +| Test.cpp:35:2:35:17 | call to BF_ofb64_encrypt | Use of banned symmetric encryption algorithm: BF. | Test.cpp:35:2:35:17 | call to BF_ofb64_encrypt | call to BF_ofb64_encrypt | +| Test.cpp:36:2:36:17 | call to Camellia_encrypt | Use of banned symmetric encryption algorithm: CAMELLIA. | Test.cpp:36:2:36:17 | call to Camellia_encrypt | call to Camellia_encrypt | +| Test.cpp:37:2:37:21 | call to Camellia_ecb_encrypt | Use of banned symmetric encryption algorithm: CAMELLIA. | Test.cpp:37:2:37:21 | call to Camellia_ecb_encrypt | call to Camellia_ecb_encrypt | +| Test.cpp:38:2:38:21 | call to Camellia_cbc_encrypt | Use of banned symmetric encryption algorithm: CAMELLIA. | Test.cpp:38:2:38:21 | call to Camellia_cbc_encrypt | call to Camellia_cbc_encrypt | +| Test.cpp:39:2:39:24 | call to Camellia_cfb128_encrypt | Use of banned symmetric encryption algorithm: CAMELLIA. | Test.cpp:39:2:39:24 | call to Camellia_cfb128_encrypt | call to Camellia_cfb128_encrypt | +| Test.cpp:40:2:40:22 | call to Camellia_cfb1_encrypt | Use of banned symmetric encryption algorithm: CAMELLIA. | Test.cpp:40:2:40:22 | call to Camellia_cfb1_encrypt | call to Camellia_cfb1_encrypt | +| Test.cpp:41:2:41:22 | call to Camellia_cfb8_encrypt | Use of banned symmetric encryption algorithm: CAMELLIA. | Test.cpp:41:2:41:22 | call to Camellia_cfb8_encrypt | call to Camellia_cfb8_encrypt | +| Test.cpp:42:2:42:24 | call to Camellia_ofb128_encrypt | Use of banned symmetric encryption algorithm: CAMELLIA. | Test.cpp:42:2:42:24 | call to Camellia_ofb128_encrypt | call to Camellia_ofb128_encrypt | +| Test.cpp:43:2:43:24 | call to Camellia_ctr128_encrypt | Use of banned symmetric encryption algorithm: CAMELLIA. | Test.cpp:43:2:43:24 | call to Camellia_ctr128_encrypt | call to Camellia_ctr128_encrypt | +| Test.cpp:44:2:44:17 | call to DES_ecb3_encrypt | Use of banned symmetric encryption algorithm: DES. | Test.cpp:44:2:44:17 | call to DES_ecb3_encrypt | call to DES_ecb3_encrypt | +| Test.cpp:45:2:45:16 | call to DES_cbc_encrypt | Use of banned symmetric encryption algorithm: DES. | Test.cpp:45:2:45:16 | call to DES_cbc_encrypt | call to DES_cbc_encrypt | +| Test.cpp:46:2:46:17 | call to DES_ncbc_encrypt | Use of banned symmetric encryption algorithm: DES. | Test.cpp:46:2:46:17 | call to DES_ncbc_encrypt | call to DES_ncbc_encrypt | +| Test.cpp:47:2:47:17 | call to DES_xcbc_encrypt | Use of banned symmetric encryption algorithm: DESX. | Test.cpp:47:2:47:17 | call to DES_xcbc_encrypt | call to DES_xcbc_encrypt | +| Test.cpp:48:2:48:16 | call to DES_cfb_encrypt | Use of banned symmetric encryption algorithm: DES. | Test.cpp:48:2:48:16 | call to DES_cfb_encrypt | call to DES_cfb_encrypt | +| Test.cpp:49:2:49:16 | call to DES_ecb_encrypt | Use of banned symmetric encryption algorithm: DES. | Test.cpp:49:2:49:16 | call to DES_ecb_encrypt | call to DES_ecb_encrypt | +| Test.cpp:50:2:50:13 | call to DES_encrypt1 | Use of banned symmetric encryption algorithm: DES. | Test.cpp:50:2:50:13 | call to DES_encrypt1 | call to DES_encrypt1 | +| Test.cpp:51:2:51:13 | call to DES_encrypt2 | Use of banned symmetric encryption algorithm: DES. | Test.cpp:51:2:51:13 | call to DES_encrypt2 | call to DES_encrypt2 | +| Test.cpp:52:2:52:13 | call to DES_encrypt3 | Use of banned symmetric encryption algorithm: DES. | Test.cpp:52:2:52:13 | call to DES_encrypt3 | call to DES_encrypt3 | +| Test.cpp:53:2:53:21 | call to DES_ede3_cbc_encrypt | Use of banned symmetric encryption algorithm: DES. | Test.cpp:53:2:53:21 | call to DES_ede3_cbc_encrypt | call to DES_ede3_cbc_encrypt | +| Test.cpp:54:2:54:18 | call to DES_ofb64_encrypt | Use of banned symmetric encryption algorithm: DES. | Test.cpp:54:2:54:18 | call to DES_ofb64_encrypt | call to DES_ofb64_encrypt | +| Test.cpp:55:2:55:17 | call to IDEA_ecb_encrypt | Use of banned symmetric encryption algorithm: IDEA. | Test.cpp:55:2:55:17 | call to IDEA_ecb_encrypt | call to IDEA_ecb_encrypt | +| Test.cpp:56:2:56:17 | call to IDEA_cbc_encrypt | Use of banned symmetric encryption algorithm: IDEA. | Test.cpp:56:2:56:17 | call to IDEA_cbc_encrypt | call to IDEA_cbc_encrypt | +| Test.cpp:57:2:57:19 | call to IDEA_cfb64_encrypt | Use of banned symmetric encryption algorithm: IDEA. | Test.cpp:57:2:57:19 | call to IDEA_cfb64_encrypt | call to IDEA_cfb64_encrypt | +| Test.cpp:58:2:58:19 | call to IDEA_ofb64_encrypt | Use of banned symmetric encryption algorithm: IDEA. | Test.cpp:58:2:58:19 | call to IDEA_ofb64_encrypt | call to IDEA_ofb64_encrypt | +| Test.cpp:59:2:59:13 | call to IDEA_encrypt | Use of banned symmetric encryption algorithm: IDEA. | Test.cpp:59:2:59:13 | call to IDEA_encrypt | call to IDEA_encrypt | +| Test.cpp:60:2:60:16 | call to RC2_ecb_encrypt | Use of banned symmetric encryption algorithm: RC2. | Test.cpp:60:2:60:16 | call to RC2_ecb_encrypt | call to RC2_ecb_encrypt | +| Test.cpp:61:2:61:12 | call to RC2_encrypt | Use of banned symmetric encryption algorithm: RC2. | Test.cpp:61:2:61:12 | call to RC2_encrypt | call to RC2_encrypt | +| Test.cpp:62:2:62:16 | call to RC2_cbc_encrypt | Use of banned symmetric encryption algorithm: RC2. | Test.cpp:62:2:62:16 | call to RC2_cbc_encrypt | call to RC2_cbc_encrypt | +| Test.cpp:63:2:63:18 | call to RC2_cfb64_encrypt | Use of banned symmetric encryption algorithm: RC2. | Test.cpp:63:2:63:18 | call to RC2_cfb64_encrypt | call to RC2_cfb64_encrypt | +| Test.cpp:64:2:64:18 | call to RC2_ofb64_encrypt | Use of banned symmetric encryption algorithm: RC2. | Test.cpp:64:2:64:18 | call to RC2_ofb64_encrypt | call to RC2_ofb64_encrypt | +| Test.cpp:65:2:65:19 | call to RC5_32_ecb_encrypt | Use of banned symmetric encryption algorithm: RC5. | Test.cpp:65:2:65:19 | call to RC5_32_ecb_encrypt | call to RC5_32_ecb_encrypt | +| Test.cpp:66:2:66:15 | call to RC5_32_encrypt | Use of banned symmetric encryption algorithm: RC5. | Test.cpp:66:2:66:15 | call to RC5_32_encrypt | call to RC5_32_encrypt | +| Test.cpp:67:2:67:19 | call to RC5_32_cbc_encrypt | Use of banned symmetric encryption algorithm: RC5. | Test.cpp:67:2:67:19 | call to RC5_32_cbc_encrypt | call to RC5_32_cbc_encrypt | +| Test.cpp:68:2:68:21 | call to RC5_32_cfb64_encrypt | Use of banned symmetric encryption algorithm: RC5. | Test.cpp:68:2:68:21 | call to RC5_32_cfb64_encrypt | call to RC5_32_cfb64_encrypt | +| Test.cpp:69:2:69:21 | call to RC5_32_ofb64_encrypt | Use of banned symmetric encryption algorithm: RC5. | Test.cpp:69:2:69:21 | call to RC5_32_ofb64_encrypt | call to RC5_32_ofb64_encrypt | +| Test.cpp:70:2:70:12 | call to RC4_set_key | Use of banned symmetric encryption algorithm: RC4. | Test.cpp:70:2:70:12 | call to RC4_set_key | call to RC4_set_key | +| Test.cpp:71:2:71:4 | call to RC4 | Use of banned symmetric encryption algorithm: RC4. | Test.cpp:71:2:71:4 | call to RC4 | call to RC4 | +| Test.cpp:160:35:160:44 | des-ede3 | Use of banned symmetric encryption algorithm: DES. | Test.cpp:160:35:160:44 | des-ede3 | des-ede3 | +| Test.cpp:161:33:161:46 | des-ede3-cbc | Use of banned symmetric encryption algorithm: DES. | Test.cpp:161:33:161:46 | des-ede3-cbc | des-ede3-cbc | +| Test.cpp:162:32:162:33 | 31 | Use of banned symmetric encryption algorithm: DES. | Test.cpp:162:32:162:33 | 31 | 31 | +| Test.cpp:164:14:164:15 | 30 | Use of banned symmetric encryption algorithm: DES. Algorithm used at sink: $@. | Test.cpp:165:32:165:34 | obj | obj | +| Test.cpp:167:13:167:25 | camellia256 | Use of banned symmetric encryption algorithm: CAMELLIA256. Algorithm used at sink: $@. | Test.cpp:168:32:168:34 | obj | obj | +| Test.cpp:169:35:169:39 | rc4 | Use of banned symmetric encryption algorithm: RC4. | Test.cpp:169:35:169:39 | rc4 | rc4 | +| Test.cpp:170:33:170:40 | rc4-40 | Use of banned symmetric encryption algorithm: RC4. | Test.cpp:170:33:170:40 | rc4-40 | rc4-40 | +| Test.cpp:171:32:171:32 | 5 | Use of banned symmetric encryption algorithm: RC4. | Test.cpp:171:32:171:32 | 5 | 5 | +| Test.cpp:173:13:173:22 | desx-cbc | Use of banned symmetric encryption algorithm: DESX. Algorithm used at sink: $@. | Test.cpp:174:32:174:34 | obj | obj | +| Test.cpp:175:35:175:42 | bf-cbc | Use of banned symmetric encryption algorithm: BF. | Test.cpp:175:35:175:42 | bf-cbc | bf-cbc | +| Test.cpp:176:33:176:44 | rc2-64-cbc | Use of banned symmetric encryption algorithm: RC2. | Test.cpp:176:33:176:44 | rc2-64-cbc | rc2-64-cbc | +| Test.cpp:177:32:177:35 | 1019 | Use of banned symmetric encryption algorithm: CHACHA20. | Test.cpp:177:32:177:35 | 1019 | 1019 | +| Test.cpp:179:14:179:16 | 813 | Use of banned symmetric encryption algorithm: GOST89. Algorithm used at sink: $@. | Test.cpp:180:32:180:34 | obj | obj | +| Test.cpp:179:14:179:16 | 813 | Use of banned symmetric encryption algorithm: GOST2814789. Algorithm used at sink: $@. | Test.cpp:180:32:180:34 | obj | obj | +| Test.cpp:182:13:182:21 | sm4-cbc | Use of banned symmetric encryption algorithm: SM4. Algorithm used at sink: $@. | Test.cpp:183:32:183:34 | obj | obj | diff --git a/cpp/ql/test/query-tests/Microsoft/Security/Cryptography/BannedEncryption/modeled_apis/WeakEncryption.qlref b/cpp/ql/test/query-tests/Microsoft/Security/Cryptography/BannedEncryption/modeled_apis/WeakEncryption.qlref new file mode 100644 index 000000000000..cfdff69c3171 --- /dev/null +++ b/cpp/ql/test/query-tests/Microsoft/Security/Cryptography/BannedEncryption/modeled_apis/WeakEncryption.qlref @@ -0,0 +1 @@ +Microsoft/Security/Cryptography/BannedEncryption.ql \ No newline at end of file diff --git a/cpp/ql/test/query-tests/Microsoft/Security/Cryptography/BannedEncryption/modeled_apis/openssl/other.h b/cpp/ql/test/query-tests/Microsoft/Security/Cryptography/BannedEncryption/modeled_apis/openssl/other.h new file mode 100644 index 000000000000..ff474684b74f --- /dev/null +++ b/cpp/ql/test/query-tests/Microsoft/Security/Cryptography/BannedEncryption/modeled_apis/openssl/other.h @@ -0,0 +1,272 @@ +struct asn1_object_st { + const char *sn, *ln; + int nid; + int length; + const unsigned char *data; /* data remains const after init */ + int flags; /* Should we free this one */ +}; +typedef struct asn1_object_st ASN1_OBJECT; + +struct evp_cipher_st { + int nid; + + int block_size; + /* Default value for variable length ciphers */ + int key_len; + int iv_len; + + // /* Legacy structure members */ + // /* Various flags */ + // unsigned long flags; + // /* How the EVP_CIPHER was created. */ + // int origin; + // /* init key */ + // int (*init) (EVP_CIPHER_CTX *ctx, const unsigned char *key, + // const unsigned char *iv, int enc); + // /* encrypt/decrypt data */ + // int (*do_cipher) (EVP_CIPHER_CTX *ctx, unsigned char *out, + // const unsigned char *in, size_t inl); + // /* cleanup ctx */ + // int (*cleanup) (EVP_CIPHER_CTX *); + // /* how big ctx->cipher_data needs to be */ + // int ctx_size; + // /* Populate a ASN1_TYPE with parameters */ + // int (*set_asn1_parameters) (EVP_CIPHER_CTX *, ASN1_TYPE *); + // /* Get parameters from a ASN1_TYPE */ + // int (*get_asn1_parameters) (EVP_CIPHER_CTX *, ASN1_TYPE *); + // /* Miscellaneous operations */ + // int (*ctrl) (EVP_CIPHER_CTX *, int type, int arg, void *ptr); + // /* Application data */ + // void *app_data; + + // /* New structure members */ + // /* Above comment to be removed when legacy has gone */ + // int name_id; + char *type_name; + const char *description; + // OSSL_PROVIDER *prov; + // CRYPTO_REF_COUNT refcnt; + // CRYPTO_RWLOCK *lock; + // OSSL_FUNC_cipher_newctx_fn *newctx; + // OSSL_FUNC_cipher_encrypt_init_fn *einit; + // OSSL_FUNC_cipher_decrypt_init_fn *dinit; + // OSSL_FUNC_cipher_update_fn *cupdate; + // OSSL_FUNC_cipher_final_fn *cfinal; + // OSSL_FUNC_cipher_cipher_fn *ccipher; + // OSSL_FUNC_cipher_freectx_fn *freectx; + // OSSL_FUNC_cipher_dupctx_fn *dupctx; + // OSSL_FUNC_cipher_get_params_fn *get_params; + // OSSL_FUNC_cipher_get_ctx_params_fn *get_ctx_params; + // OSSL_FUNC_cipher_set_ctx_params_fn *set_ctx_params; + // OSSL_FUNC_cipher_gettable_params_fn *gettable_params; + // OSSL_FUNC_cipher_gettable_ctx_params_fn *gettable_ctx_params; + // OSSL_FUNC_cipher_settable_ctx_params_fn *settable_ctx_params; +} /* EVP_CIPHER */ ; + +typedef struct evp_cipher_st EVP_CIPHER; + +typedef struct rc4_key_st { + int x, y; + int data[256]; +} RC4_KEY; + +struct key_st { + unsigned long rd_key[4]; + int rounds; +}; +typedef struct key_st AES_KEY, BF_KEY, CAMELLIA_KEY, DES_key_schedule, IDEA_KEY_SCHEDULE, RC2_KEY, RC5_32_KEY; + +typedef unsigned int DES_LONG, BF_LONG; +typedef unsigned char DES_cblock[8]; +typedef unsigned char const_DES_cblock[8]; +typedef unsigned int size_t; + + +#define CAMELLIA_BLOCK_SIZE 4 + + +// Symmetric Cipher Algorithm sinks +EVP_CIPHER *EVP_CIPHER_fetch(void *ctx, const char *algorithm, const char *properties); +EVP_CIPHER *EVP_get_cipherbyname(const char *name); +EVP_CIPHER *EVP_get_cipherbynid(int nid); +EVP_CIPHER *EVP_get_cipherbyobj(const ASN1_OBJECT *a); + +// ----------https://www.openssl.org/docs/man1.1.1/man3/OBJ_obj2txt.html +ASN1_OBJECT *OBJ_nid2obj(int n); +char *OBJ_nid2ln(int n); +char *OBJ_nid2sn(int n); + +int OBJ_obj2nid(const ASN1_OBJECT *o); +int OBJ_ln2nid(const char *ln); +int OBJ_sn2nid(const char *sn); + +int OBJ_txt2nid(const char *s); + +ASN1_OBJECT *OBJ_txt2obj(const char *s, int no_name); +int OBJ_obj2txt(char *buf, int buf_len, const ASN1_OBJECT *a, int no_name); + +int i2t_ASN1_OBJECT(char *buf, int buf_len, const ASN1_OBJECT *a); + +int OBJ_cmp(const ASN1_OBJECT *a, const ASN1_OBJECT *b); +ASN1_OBJECT *OBJ_dup(const ASN1_OBJECT *o); + +int OBJ_create(const char *oid, const char *sn, const char *ln); +//------------- +//https://www.openssl.org/docs/man3.0/man3/EVP_CIPHER_get0_name.html +char *EVP_CIPHER_get0_name(const EVP_CIPHER *cipher); +//----- + +void AES_encrypt(const unsigned char *in, unsigned char *out, + const AES_KEY *key); +void AES_ecb_encrypt(const unsigned char *in, unsigned char *out, + const AES_KEY *key, const int enc); +void AES_cbc_encrypt(const unsigned char *in, unsigned char *out, + size_t length, const AES_KEY *key, + unsigned char *ivec, const int enc); +void AES_cfb128_encrypt(const unsigned char *in, unsigned char *out, + size_t length, const AES_KEY *key, + unsigned char *ivec, int *num, const int enc); +void AES_cfb1_encrypt(const unsigned char *in, unsigned char *out, + size_t length, const AES_KEY *key, + unsigned char *ivec, int *num, const int enc); +void AES_cfb8_encrypt(const unsigned char *in, unsigned char *out, + size_t length, const AES_KEY *key, + unsigned char *ivec, int *num, const int enc); +void AES_ofb128_encrypt(const unsigned char *in, unsigned char *out, + size_t length, const AES_KEY *key, + unsigned char *ivec, int *num); +/* NB: the IV is _two_ blocks long */ +void AES_ige_encrypt(const unsigned char *in, unsigned char *out, + size_t length, const AES_KEY *key, + unsigned char *ivec, const int enc); +/* NB: the IV is _four_ blocks long */ +void AES_bi_ige_encrypt(const unsigned char *in, unsigned char *out, + size_t length, const AES_KEY *key, + const AES_KEY *key2, const unsigned char *ivec, + const int enc); +void BF_encrypt(BF_LONG *data, const BF_KEY *key); +void BF_decrypt(BF_LONG *data, const BF_KEY *key); + +void BF_ecb_encrypt(const unsigned char *in, unsigned char *out, + const BF_KEY *key, int enc); +void BF_cbc_encrypt(const unsigned char *in, unsigned char *out, long length, + const BF_KEY *schedule, unsigned char *ivec, int enc); +void BF_cfb64_encrypt(const unsigned char *in, unsigned char *out, + long length, const BF_KEY *schedule, + unsigned char *ivec, int *num, int enc); +void BF_ofb64_encrypt(const unsigned char *in, unsigned char *out, + long length, const BF_KEY *schedule, + unsigned char *ivec, int *num); +void Camellia_encrypt(const unsigned char *in, unsigned char *out, + const CAMELLIA_KEY *key); +void Camellia_ecb_encrypt(const unsigned char *in, unsigned char *out, + const CAMELLIA_KEY *key, const int enc); +void Camellia_cbc_encrypt(const unsigned char *in, unsigned char *out, + size_t length, const CAMELLIA_KEY *key, + unsigned char *ivec, const int enc); +void Camellia_cfb128_encrypt(const unsigned char *in, unsigned char *out, + size_t length, const CAMELLIA_KEY *key, + unsigned char *ivec, int *num, const int enc); +void Camellia_cfb1_encrypt(const unsigned char *in, unsigned char *out, + size_t length, const CAMELLIA_KEY *key, + unsigned char *ivec, int *num, const int enc); +void Camellia_cfb8_encrypt(const unsigned char *in, unsigned char *out, + size_t length, const CAMELLIA_KEY *key, + unsigned char *ivec, int *num, const int enc); +void Camellia_ofb128_encrypt(const unsigned char *in, unsigned char *out, + size_t length, const CAMELLIA_KEY *key, + unsigned char *ivec, int *num); +void Camellia_ctr128_encrypt(const unsigned char *in, unsigned char *out, + size_t length, const CAMELLIA_KEY *key, + unsigned char ivec[CAMELLIA_BLOCK_SIZE], + unsigned char ecount_buf[CAMELLIA_BLOCK_SIZE], + unsigned int *num); +void DES_ecb3_encrypt(const_DES_cblock *input, DES_cblock *output, + DES_key_schedule *ks1, DES_key_schedule *ks2, + DES_key_schedule *ks3, int enc); +void DES_cbc_encrypt(const unsigned char *input, unsigned char *output, + long length, DES_key_schedule *schedule, + DES_cblock *ivec, int enc); +void DES_ncbc_encrypt(const unsigned char *input, unsigned char *output, + long length, DES_key_schedule *schedule, + DES_cblock *ivec, int enc); +void DES_xcbc_encrypt(const unsigned char *input, unsigned char *output, + long length, DES_key_schedule *schedule, + DES_cblock *ivec, const_DES_cblock *inw, + const_DES_cblock *outw, int enc); +void DES_cfb_encrypt(const unsigned char *in, unsigned char *out, int numbits, + long length, DES_key_schedule *schedule, + DES_cblock *ivec, int enc); +void DES_ecb_encrypt(const_DES_cblock *input, DES_cblock *output, + DES_key_schedule *ks, int enc); +void DES_encrypt1(DES_LONG *data, DES_key_schedule *ks, int enc); +void DES_encrypt2(DES_LONG *data, DES_key_schedule *ks, int enc); +void DES_encrypt3(DES_LONG *data, DES_key_schedule *ks1, + DES_key_schedule *ks2, DES_key_schedule *ks3); +void DES_ede3_cbc_encrypt(const unsigned char *input, unsigned char *output, + long length, + DES_key_schedule *ks1, DES_key_schedule *ks2, + DES_key_schedule *ks3, DES_cblock *ivec, int enc); +void DES_ede3_cfb64_encrypt(const unsigned char *in, unsigned char *out, + long length, DES_key_schedule *ks1, + DES_key_schedule *ks2, DES_key_schedule *ks3, + DES_cblock *ivec, int *num, int enc); +void DES_ede3_cfb_encrypt(const unsigned char *in, unsigned char *out, + int numbits, long length, DES_key_schedule *ks1, + DES_key_schedule *ks2, DES_key_schedule *ks3, + DES_cblock *ivec, int enc); +void DES_ede3_ofb64_encrypt(const unsigned char *in, unsigned char *out, + long length, DES_key_schedule *ks1, + DES_key_schedule *ks2, DES_key_schedule *ks3, + DES_cblock *ivec, int *num); +void DES_ofb_encrypt(const unsigned char *in, unsigned char *out, int numbits, + long length, DES_key_schedule *schedule, + DES_cblock *ivec); +void DES_pcbc_encrypt(const unsigned char *input, unsigned char *output, + long length, DES_key_schedule *schedule, + DES_cblock *ivec, int enc); +void DES_cfb64_encrypt(const unsigned char *in, unsigned char *out, + long length, DES_key_schedule *schedule, + DES_cblock *ivec, int *num, int enc); +void DES_ofb64_encrypt(const unsigned char *in, unsigned char *out, + long length, DES_key_schedule *schedule, + DES_cblock *ivec, int *num); +void IDEA_ecb_encrypt(const unsigned char *in, unsigned char *out, + IDEA_KEY_SCHEDULE *ks); +void IDEA_set_encrypt_key(const unsigned char *key, IDEA_KEY_SCHEDULE *ks); +void IDEA_cbc_encrypt(const unsigned char *in, unsigned char *out, + long length, IDEA_KEY_SCHEDULE *ks, unsigned char *iv, + int enc); +void IDEA_cfb64_encrypt(const unsigned char *in, unsigned char *out, + long length, IDEA_KEY_SCHEDULE *ks, unsigned char *iv, + int *num, int enc); +void IDEA_ofb64_encrypt(const unsigned char *in, unsigned char *out, + long length, IDEA_KEY_SCHEDULE *ks, unsigned char *iv, + int *num); +void IDEA_encrypt(unsigned long *in, IDEA_KEY_SCHEDULE *ks); +void RC2_ecb_encrypt(const unsigned char *in, unsigned char *out, + RC2_KEY *key, int enc); +void RC2_encrypt(unsigned long *data, RC2_KEY *key); +void RC2_cbc_encrypt(const unsigned char *in, unsigned char *out, long length, + RC2_KEY *ks, unsigned char *iv, int enc); +void RC2_cfb64_encrypt(const unsigned char *in, unsigned char *out, + long length, RC2_KEY *schedule, unsigned char *ivec, + int *num, int enc); +void RC2_ofb64_encrypt(const unsigned char *in, unsigned char *out, + long length, RC2_KEY *schedule, unsigned char *ivec, + int *num); +void RC5_32_ecb_encrypt(const unsigned char *in, unsigned char *out, + RC5_32_KEY *key, int enc); +void RC5_32_encrypt(unsigned long *data, RC5_32_KEY *key); +void RC5_32_cbc_encrypt(const unsigned char *in, unsigned char *out, + long length, RC5_32_KEY *ks, unsigned char *iv, + int enc); +void RC5_32_cfb64_encrypt(const unsigned char *in, unsigned char *out, + long length, RC5_32_KEY *schedule, + unsigned char *ivec, int *num, int enc); +void RC5_32_ofb64_encrypt(const unsigned char *in, unsigned char *out, + long length, RC5_32_KEY *schedule, + unsigned char *ivec, int *num); +void RC4_set_key(RC4_KEY *key, int len, const unsigned char *data); +void RC4(RC4_KEY *key, size_t len, const unsigned char *indata, + unsigned char *outdata); diff --git a/cpp/ql/test/query-tests/Microsoft/Security/Cryptography/BannedModesCapi/BannedModesCapi.expected b/cpp/ql/test/query-tests/Microsoft/Security/Cryptography/BannedModesCapi/BannedModesCapi.expected new file mode 100644 index 000000000000..dc6be6d265af --- /dev/null +++ b/cpp/ql/test/query-tests/Microsoft/Security/Cryptography/BannedModesCapi/BannedModesCapi.expected @@ -0,0 +1,7 @@ +| Test.cpp:100:2:100:17 | call to CryptSetKeyParam | Call to 'CryptSetKeyParam' function with argument dwParam = KP_MODE is setting up a banned block cipher mode. | +| Test.cpp:114:2:114:17 | call to CryptSetKeyParam | Call to 'CryptSetKeyParam' function with argument dwParam = KP_MODE is setting up a banned block cipher mode. | +| Test.cpp:116:2:116:17 | call to CryptSetKeyParam | Call to 'CryptSetKeyParam' function with argument dwParam = KP_MODE is setting up a banned block cipher mode. | +| Test.cpp:118:2:118:17 | call to CryptSetKeyParam | Call to 'CryptSetKeyParam' function with argument dwParam = KP_MODE is setting up a banned block cipher mode. | +| Test.cpp:120:2:120:17 | call to CryptSetKeyParam | Call to 'CryptSetKeyParam' function with argument dwParam = KP_MODE is setting up a banned block cipher mode. | +| Test.cpp:122:2:122:17 | call to CryptSetKeyParam | Call to 'CryptSetKeyParam' function with argument dwParam = KP_MODE is setting up a banned block cipher mode. | +| Test.cpp:124:2:124:43 | call to CryptSetKeyParam | Call to 'CryptSetKeyParam' function with argument dwParam = KP_MODE is setting up a banned block cipher mode. | diff --git a/cpp/ql/test/query-tests/Microsoft/Security/Cryptography/BannedModesCapi/BannedModesCapi.qlref b/cpp/ql/test/query-tests/Microsoft/Security/Cryptography/BannedModesCapi/BannedModesCapi.qlref new file mode 100644 index 000000000000..c7c219aac416 --- /dev/null +++ b/cpp/ql/test/query-tests/Microsoft/Security/Cryptography/BannedModesCapi/BannedModesCapi.qlref @@ -0,0 +1 @@ +Microsoft/Security/Cryptography/BannedModesCAPI.ql \ No newline at end of file diff --git a/cpp/ql/test/query-tests/Microsoft/Security/Cryptography/BannedModesCapi/Test.cpp b/cpp/ql/test/query-tests/Microsoft/Security/Cryptography/BannedModesCapi/Test.cpp new file mode 100644 index 000000000000..997568c0b20f --- /dev/null +++ b/cpp/ql/test/query-tests/Microsoft/Security/Cryptography/BannedModesCapi/Test.cpp @@ -0,0 +1,133 @@ +#define CONST const + +typedef unsigned long DWORD; +typedef int BOOL; +typedef unsigned char BYTE; +typedef unsigned long ULONG_PTR; +typedef unsigned long *PULONG_PTR; +typedef wchar_t WCHAR; // wc, 16-bit UNICODE character +typedef void *PVOID; +typedef CONST WCHAR *LPCWSTR, *PCWSTR; +typedef PVOID BCRYPT_ALG_HANDLE; +typedef long LONG; +typedef unsigned long ULONG; +typedef ULONG *PULONG; +typedef LONG NTSTATUS; +typedef ULONG_PTR HCRYPTHASH; +typedef ULONG_PTR HCRYPTPROV; +typedef ULONG_PTR HCRYPTKEY; +typedef ULONG_PTR HCRYPTHASH; +typedef unsigned int ALG_ID; + +// dwParam +#define KP_IV 1 // Initialization vector +#define KP_SALT 2 // Salt value +#define KP_PADDING 3 // Padding values +#define KP_MODE 4 // Mode of the cipher +#define KP_MODE_BITS 5 // Number of bits to feedback +#define KP_PERMISSIONS 6 // Key permissions DWORD +#define KP_ALGID 7 // Key algorithm +#define KP_BLOCKLEN 8 // Block size of the cipher +#define KP_KEYLEN 9 // Length of key in bits +#define KP_SALT_EX 10 // Length of salt in bytes +#define KP_P 11 // DSS/Diffie-Hellman P value +#define KP_G 12 // DSS/Diffie-Hellman G value +#define KP_Q 13 // DSS Q value +#define KP_X 14 // Diffie-Hellman X value +#define KP_Y 15 // Y value +#define KP_RA 16 // Fortezza RA value +#define KP_RB 17 // Fortezza RB value +#define KP_INFO 18 // for putting information into an RSA envelope +#define KP_EFFECTIVE_KEYLEN 19 // setting and getting RC2 effective key length +#define KP_SCHANNEL_ALG 20 // for setting the Secure Channel algorithms +#define KP_CLIENT_RANDOM 21 // for setting the Secure Channel client random data +#define KP_SERVER_RANDOM 22 // for setting the Secure Channel server random data +#define KP_RP 23 +#define KP_PRECOMP_MD5 24 +#define KP_PRECOMP_SHA 25 +#define KP_CERTIFICATE 26 // for setting Secure Channel certificate data (PCT1) +#define KP_CLEAR_KEY 27 // for setting Secure Channel clear key data (PCT1) +#define KP_PUB_EX_LEN 28 +#define KP_PUB_EX_VAL 29 +#define KP_KEYVAL 30 +#define KP_ADMIN_PIN 31 +#define KP_KEYEXCHANGE_PIN 32 +#define KP_SIGNATURE_PIN 33 +#define KP_PREHASH 34 +#define KP_ROUNDS 35 +#define KP_OAEP_PARAMS 36 // for setting OAEP params on RSA keys +#define KP_CMS_KEY_INFO 37 +#define KP_CMS_DH_KEY_INFO 38 +#define KP_PUB_PARAMS 39 // for setting public parameters +#define KP_VERIFY_PARAMS 40 // for verifying DSA and DH parameters +#define KP_HIGHEST_VERSION 41 // for TLS protocol version setting +#define KP_GET_USE_COUNT 42 // for use with PP_CRYPT_COUNT_KEY_USE contexts +#define KP_PIN_ID 43 +#define KP_PIN_INFO 44 + +// KP_PADDING +#define PKCS5_PADDING 1 // PKCS 5 (sec 6.2) padding method +#define RANDOM_PADDING 2 +#define ZERO_PADDING 3 + +// KP_MODE +#define CRYPT_MODE_CBC 1 // Cipher block chaining +#define CRYPT_MODE_ECB 2 // Electronic code book +#define CRYPT_MODE_OFB 3 // Output feedback mode +#define CRYPT_MODE_CFB 4 // Cipher feedback mode +#define CRYPT_MODE_CTS 5 // Ciphertext stealing mode + +BOOL +CryptSetKeyParam( + HCRYPTKEY hKey, + DWORD dwParam, + CONST BYTE *pbData, + DWORD dwFlags +); + +BOOL +SomeOtherFunction( + HCRYPTKEY hKey, + DWORD dwParam, + CONST BYTE *pbData, + DWORD dwFlags +); +void +DummyFunction( + DWORD dwParam, + ALG_ID dwData) +{ + CryptSetKeyParam(0, dwParam, (BYTE*)&dwData, 0); +} + + +// Macro testing +#define MACRO_INVOCATION_SETKPMODE(p) { DWORD dwData = p; \ + CryptSetKeyParam(0, KP_MODE, (BYTE*)&dwData, 0); } + +int main() +{ + DWORD val = 0; + //////////////////////////// + // Should fire an event + val = CRYPT_MODE_ECB; + CryptSetKeyParam(0, KP_MODE, (BYTE*)&val, 0); + val = CRYPT_MODE_OFB; + CryptSetKeyParam(0, KP_MODE, (BYTE*)&val, 0); + val = CRYPT_MODE_CFB; + CryptSetKeyParam(0, KP_MODE, (BYTE*)&val, 0); + val = CRYPT_MODE_CTS; + CryptSetKeyParam(0, KP_MODE, (BYTE*)&val, 0); + val = 6; + CryptSetKeyParam(0, KP_MODE, (BYTE*)&val, 0); + DummyFunction(KP_MODE, CRYPT_MODE_ECB); + MACRO_INVOCATION_SETKPMODE(CRYPT_MODE_CTS) + + //////////////////////////// + // Should not fire an event + val = CRYPT_MODE_CBC; + CryptSetKeyParam(0, KP_MODE, (BYTE*)&val, 0); + val = CRYPT_MODE_ECB; + CryptSetKeyParam(0, KP_PADDING, (BYTE*)&val, 0); + SomeOtherFunction(0, KP_MODE, (BYTE*)&val, 0); +} \ No newline at end of file diff --git a/cpp/ql/test/query-tests/Microsoft/Security/Cryptography/BannedModesCng/BannedModesCng.expected b/cpp/ql/test/query-tests/Microsoft/Security/Cryptography/BannedModesCng/BannedModesCng.expected new file mode 100644 index 000000000000..f3ba4ff16de3 --- /dev/null +++ b/cpp/ql/test/query-tests/Microsoft/Security/Cryptography/BannedModesCng/BannedModesCng.expected @@ -0,0 +1,8 @@ +| Test.cpp:57:2:57:18 | call to BCryptSetProperty | Call to 'BCryptSetProperty' function with argument pszProperty = "ChainingMode" is setting up a banned block cipher mode. | +| Test.cpp:71:2:71:18 | call to BCryptSetProperty | Call to 'BCryptSetProperty' function with argument pszProperty = "ChainingMode" is setting up a banned block cipher mode. | +| Test.cpp:73:2:73:18 | call to BCryptSetProperty | Call to 'BCryptSetProperty' function with argument pszProperty = "ChainingMode" is setting up a banned block cipher mode. | +| Test.cpp:75:2:75:18 | call to BCryptSetProperty | Call to 'BCryptSetProperty' function with argument pszProperty = "ChainingMode" is setting up a banned block cipher mode. | +| Test.cpp:77:2:77:18 | call to BCryptSetProperty | Call to 'BCryptSetProperty' function with argument pszProperty = "ChainingMode" is setting up a banned block cipher mode. | +| Test.cpp:79:2:79:18 | call to BCryptSetProperty | Call to 'BCryptSetProperty' function with argument pszProperty = "ChainingMode" is setting up a banned block cipher mode. | +| Test.cpp:81:2:81:18 | call to BCryptSetProperty | Call to 'BCryptSetProperty' function with argument pszProperty = "ChainingMode" is setting up a banned block cipher mode. | +| Test.cpp:83:2:83:50 | call to BCryptSetProperty | Call to 'BCryptSetProperty' function with argument pszProperty = "ChainingMode" is setting up a banned block cipher mode. | diff --git a/cpp/ql/test/query-tests/Microsoft/Security/Cryptography/BannedModesCng/BannedModesCng.qlref b/cpp/ql/test/query-tests/Microsoft/Security/Cryptography/BannedModesCng/BannedModesCng.qlref new file mode 100644 index 000000000000..ed229dfac761 --- /dev/null +++ b/cpp/ql/test/query-tests/Microsoft/Security/Cryptography/BannedModesCng/BannedModesCng.qlref @@ -0,0 +1 @@ +Microsoft/Security/Cryptography/BannedModesCNG.ql \ No newline at end of file diff --git a/cpp/ql/test/query-tests/Microsoft/Security/Cryptography/BannedModesCng/Test.cpp b/cpp/ql/test/query-tests/Microsoft/Security/Cryptography/BannedModesCng/Test.cpp new file mode 100644 index 000000000000..8a260c480bd6 --- /dev/null +++ b/cpp/ql/test/query-tests/Microsoft/Security/Cryptography/BannedModesCng/Test.cpp @@ -0,0 +1,93 @@ +#define CONST const + +typedef unsigned long DWORD; +typedef int BOOL; +typedef unsigned char BYTE; +typedef unsigned long ULONG_PTR; +typedef unsigned long *PULONG_PTR; +typedef wchar_t WCHAR; // wc, 16-bit UNICODE character +typedef void *PVOID; +typedef CONST WCHAR *LPCWSTR, *PCWSTR; +typedef PVOID BCRYPT_ALG_HANDLE; +typedef long LONG; +typedef unsigned long ULONG; +typedef ULONG *PULONG; +typedef LONG NTSTATUS; +typedef ULONG_PTR HCRYPTHASH; +typedef ULONG_PTR HCRYPTPROV; +typedef ULONG_PTR HCRYPTKEY; +typedef ULONG_PTR HCRYPTHASH; +typedef unsigned int ALG_ID; +typedef PVOID BCRYPT_HANDLE; +typedef unsigned char UCHAR; +typedef UCHAR *PUCHAR; + +// Property Strings +#define BCRYPT_CHAIN_MODE_NA L"ChainingModeN/A" +#define BCRYPT_CHAIN_MODE_CBC L"ChainingModeCBC" +#define BCRYPT_CHAIN_MODE_ECB L"ChainingModeECB" +#define BCRYPT_CHAIN_MODE_CFB L"ChainingModeCFB" +#define BCRYPT_CHAIN_MODE_CCM L"ChainingModeCCM" +#define BCRYPT_CHAIN_MODE_GCM L"ChainingModeGCM" + +#define BCRYPT_CHAINING_MODE L"ChainingMode" +#define BCRYPT_PADDING_SCHEMES L"PaddingSchemes" + +NTSTATUS +BCryptSetProperty( + BCRYPT_HANDLE hObject, + LPCWSTR pszProperty, + PUCHAR pbInput, + ULONG cbInput, + ULONG dwFlags); + +NTSTATUS +AnyFunctionName( + BCRYPT_HANDLE hObject, + LPCWSTR pszProperty, + PUCHAR pbInput, + ULONG cbInput, + ULONG dwFlags); + +void +DummyFunction( + LPCWSTR pszProperty, + LPCWSTR pszMode) +{ + BCryptSetProperty(0, pszProperty, (PUCHAR)&pszMode, 0, 0); +} + + +// Macro testing +#define MACRO_INVOCATION_SETKPMODE(p) { LPCWSTR pszMode = p; \ + BCryptSetProperty(0, BCRYPT_CHAINING_MODE, (PUCHAR)&pszMode, 0, 0); } + +int main() +{ + LPCWSTR val = 0; + //////////////////////////// + // Should fire an event + val = BCRYPT_CHAIN_MODE_NA; + BCryptSetProperty(0, BCRYPT_CHAINING_MODE, (PUCHAR)&val, 0, 0); + val = BCRYPT_CHAIN_MODE_ECB; + BCryptSetProperty(0, BCRYPT_CHAINING_MODE, (PUCHAR)&val, 0, 0); + val = BCRYPT_CHAIN_MODE_CFB; + BCryptSetProperty(0, BCRYPT_CHAINING_MODE, (PUCHAR)&val, 0, 0); + val = BCRYPT_CHAIN_MODE_CCM; + BCryptSetProperty(0, BCRYPT_CHAINING_MODE, (PUCHAR)&val, 0, 0); + val = BCRYPT_CHAIN_MODE_GCM; + BCryptSetProperty(0, BCRYPT_CHAINING_MODE, (PUCHAR)&val, 0, 0); + val = L"ChainingModeNEW"; + BCryptSetProperty(0, BCRYPT_CHAINING_MODE, (PUCHAR)&val, 0, 0); + DummyFunction(BCRYPT_CHAINING_MODE, BCRYPT_CHAIN_MODE_GCM); + MACRO_INVOCATION_SETKPMODE(BCRYPT_CHAIN_MODE_ECB) + + //////////////////////////// + // Should not fire an event + val = BCRYPT_CHAIN_MODE_CBC; + BCryptSetProperty(0, BCRYPT_CHAINING_MODE, (PUCHAR)&val, 0, 0); + val = BCRYPT_CHAIN_MODE_ECB; + BCryptSetProperty(0, BCRYPT_PADDING_SCHEMES, (PUCHAR)&val, 0, 0); + val = BCRYPT_CHAIN_MODE_ECB; + AnyFunctionName(0, BCRYPT_CHAINING_MODE, (PUCHAR)&val, 0, 0); +} \ No newline at end of file diff --git a/cpp/ql/test/query-tests/Microsoft/Security/Cryptography/HardCodedIVCNG/HardCodedIVCNG.expected b/cpp/ql/test/query-tests/Microsoft/Security/Cryptography/HardCodedIVCNG/HardCodedIVCNG.expected new file mode 100644 index 000000000000..093a13569963 --- /dev/null +++ b/cpp/ql/test/query-tests/Microsoft/Security/Cryptography/HardCodedIVCNG/HardCodedIVCNG.expected @@ -0,0 +1 @@ +| Test.cpp:56:16:60:2 | {...} | Calling BCryptEncrypt with a hard-coded IV on function | diff --git a/cpp/ql/test/query-tests/Microsoft/Security/Cryptography/HardCodedIVCNG/HardCodedIVCNG.qlref b/cpp/ql/test/query-tests/Microsoft/Security/Cryptography/HardCodedIVCNG/HardCodedIVCNG.qlref new file mode 100644 index 000000000000..a04eca59ce5f --- /dev/null +++ b/cpp/ql/test/query-tests/Microsoft/Security/Cryptography/HardCodedIVCNG/HardCodedIVCNG.qlref @@ -0,0 +1 @@ +Microsoft/Security/Cryptography/HardcodedIVCNG.ql \ No newline at end of file diff --git a/cpp/ql/test/query-tests/Microsoft/Security/Cryptography/HardCodedIVCNG/Test.cpp b/cpp/ql/test/query-tests/Microsoft/Security/Cryptography/HardCodedIVCNG/Test.cpp new file mode 100644 index 000000000000..32502efeb032 --- /dev/null +++ b/cpp/ql/test/query-tests/Microsoft/Security/Cryptography/HardCodedIVCNG/Test.cpp @@ -0,0 +1,75 @@ +#define CONST const + +typedef unsigned long DWORD; +typedef int BOOL; +typedef unsigned char BYTE; +typedef unsigned long ULONG_PTR; +typedef unsigned long *PULONG_PTR; +typedef wchar_t WCHAR; // wc, 16-bit UNICODE character +typedef void *PVOID; +typedef CONST WCHAR *LPCWSTR, *PCWSTR; +typedef PVOID BCRYPT_ALG_HANDLE; +typedef PVOID BCRYPT_KEY_HANDLE; +typedef long LONG; +typedef unsigned long ULONG; +typedef ULONG *PULONG; +typedef LONG NTSTATUS; +typedef ULONG_PTR HCRYPTHASH; +typedef ULONG_PTR HCRYPTPROV; +typedef ULONG_PTR HCRYPTKEY; +typedef ULONG_PTR HCRYPTHASH; +typedef unsigned int ALG_ID; + +typedef unsigned char UCHAR; +typedef UCHAR *PUCHAR; +#define VOID void + +NTSTATUS +BCryptEncrypt( + BCRYPT_KEY_HANDLE hKey, + PUCHAR pbInput, + ULONG cbInput, + VOID *pPaddingInfo, + PUCHAR pbIV, + ULONG cbIV, + PUCHAR pbOutput, + ULONG cbOutput, + ULONG *pcbResult, + ULONG dwFlags); + + +static unsigned long int next = 1; + +int rand(void) // RAND_MAX assumed to be 32767 +{ + next = next * 1103515245 + 12345; + unsigned int tmp = (next / 65536) % 32768; + if (tmp % next) + { + next = (next / 65526) % tmp; + } + return next; +} + +int main() +{ + BYTE rgbIV[] = + { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F + }; + + BYTE* pIV = new BYTE(16); + // rand() is not a good source for IV, + // but I am avoiding calling a CSPRGenerator for this test. + for (int i = 0; i < 16; i++) + { + pIV[i] = (BYTE)rand(); + } + + BCryptEncrypt(0, 0, 0, 0, rgbIV, 16, 0, 0, 0, 0); // Must be flagged + + BCryptEncrypt(0, 0, 0, 0, pIV, 16, 0, 0, 0, 0); // Should not be flagged + + delete[] pIV; +} \ No newline at end of file diff --git a/cpp/ql/test/query-tests/Microsoft/Security/Cryptography/WeakKDF/WeakKDFBannedHashAlgorithm.expected b/cpp/ql/test/query-tests/Microsoft/Security/Cryptography/WeakKDF/WeakKDFBannedHashAlgorithm.expected new file mode 100644 index 000000000000..7f732b4a391e --- /dev/null +++ b/cpp/ql/test/query-tests/Microsoft/Security/Cryptography/WeakKDF/WeakKDFBannedHashAlgorithm.expected @@ -0,0 +1 @@ +| test.cpp:31:36:31:41 | handle | BCRYPT_ALG_HANDLE is passed to this to KDF derived from insecure hashing function $@. Must use SHA256 or higher. | test.cpp:19:51:19:70 | MD5 | MD5 | diff --git a/cpp/ql/test/query-tests/Microsoft/Security/Cryptography/WeakKDF/WeakKDFBannedHashAlgorithm.qlref b/cpp/ql/test/query-tests/Microsoft/Security/Cryptography/WeakKDF/WeakKDFBannedHashAlgorithm.qlref new file mode 100644 index 000000000000..03460127fa91 --- /dev/null +++ b/cpp/ql/test/query-tests/Microsoft/Security/Cryptography/WeakKDF/WeakKDFBannedHashAlgorithm.qlref @@ -0,0 +1 @@ +Microsoft/Security/Cryptography/WeakKDFBannedHashAlgorithm.ql \ No newline at end of file diff --git a/cpp/ql/test/query-tests/Microsoft/Security/Cryptography/WeakKDF/WeakKDFLowIterationCount.expected b/cpp/ql/test/query-tests/Microsoft/Security/Cryptography/WeakKDF/WeakKDFLowIterationCount.expected new file mode 100644 index 000000000000..9ecbbd43c49e --- /dev/null +++ b/cpp/ql/test/query-tests/Microsoft/Security/Cryptography/WeakKDF/WeakKDFLowIterationCount.expected @@ -0,0 +1 @@ +| test.cpp:31:97:31:100 | 2048 | Iteration count $@ is passed to this to KDF. Use at least 100000 iterations when deriving cryptographic key from password. | test.cpp:31:97:31:100 | 2048 | 2048 | diff --git a/cpp/ql/test/query-tests/Microsoft/Security/Cryptography/WeakKDF/WeakKDFLowIterationCount.qlref b/cpp/ql/test/query-tests/Microsoft/Security/Cryptography/WeakKDF/WeakKDFLowIterationCount.qlref new file mode 100644 index 000000000000..9f2dff690d78 --- /dev/null +++ b/cpp/ql/test/query-tests/Microsoft/Security/Cryptography/WeakKDF/WeakKDFLowIterationCount.qlref @@ -0,0 +1 @@ +Microsoft/Security/Cryptography/WeakKDFLowIterationCount.ql \ No newline at end of file diff --git a/cpp/ql/test/query-tests/Microsoft/Security/Cryptography/WeakKDF/WeakKDFSmallKeyLength.expected b/cpp/ql/test/query-tests/Microsoft/Security/Cryptography/WeakKDF/WeakKDFSmallKeyLength.expected new file mode 100644 index 000000000000..2555150a2d95 --- /dev/null +++ b/cpp/ql/test/query-tests/Microsoft/Security/Cryptography/WeakKDF/WeakKDFSmallKeyLength.expected @@ -0,0 +1 @@ +| test.cpp:31:123:31:123 | 8 | Key size $@ is passed to this to KDF. Use at least 16 bytes for key length when deriving cryptographic key from password. | test.cpp:31:123:31:123 | 8 | 8 | diff --git a/cpp/ql/test/query-tests/Microsoft/Security/Cryptography/WeakKDF/WeakKDFSmallKeyLength.qlref b/cpp/ql/test/query-tests/Microsoft/Security/Cryptography/WeakKDF/WeakKDFSmallKeyLength.qlref new file mode 100644 index 000000000000..d0fe39707800 --- /dev/null +++ b/cpp/ql/test/query-tests/Microsoft/Security/Cryptography/WeakKDF/WeakKDFSmallKeyLength.qlref @@ -0,0 +1 @@ +Microsoft/Security/Cryptography/WeakKDFSmallKeyLength.ql \ No newline at end of file diff --git a/cpp/ql/test/query-tests/Microsoft/Security/Cryptography/WeakKDF/WeakKDFSmallSaltSize.expected b/cpp/ql/test/query-tests/Microsoft/Security/Cryptography/WeakKDF/WeakKDFSmallSaltSize.expected new file mode 100644 index 000000000000..d68b6d8274a4 --- /dev/null +++ b/cpp/ql/test/query-tests/Microsoft/Security/Cryptography/WeakKDF/WeakKDFSmallSaltSize.expected @@ -0,0 +1 @@ +| test.cpp:31:94:31:94 | 8 | Salt size $@ is passed to this to KDF. Use at least 16 bytes for salt size when deriving cryptographic key from password. | test.cpp:31:94:31:94 | 8 | 8 | diff --git a/cpp/ql/test/query-tests/Microsoft/Security/Cryptography/WeakKDF/WeakKDFSmallSaltSize.qlref b/cpp/ql/test/query-tests/Microsoft/Security/Cryptography/WeakKDF/WeakKDFSmallSaltSize.qlref new file mode 100644 index 000000000000..4f097d2b2abf --- /dev/null +++ b/cpp/ql/test/query-tests/Microsoft/Security/Cryptography/WeakKDF/WeakKDFSmallSaltSize.qlref @@ -0,0 +1 @@ +Microsoft/Security/Cryptography/WeakKDFSmallSaltSize.ql \ No newline at end of file diff --git a/cpp/ql/test/query-tests/Microsoft/Security/Cryptography/WeakKDF/bcrypt.h b/cpp/ql/test/query-tests/Microsoft/Security/Cryptography/WeakKDF/bcrypt.h new file mode 100644 index 000000000000..3e9fc08d7902 --- /dev/null +++ b/cpp/ql/test/query-tests/Microsoft/Security/Cryptography/WeakKDF/bcrypt.h @@ -0,0 +1,69 @@ +#define CONST const + +typedef unsigned long DWORD; +typedef int BOOL; +typedef unsigned char BYTE; +typedef unsigned long ULONG_PTR; +typedef unsigned long *PULONG_PTR; +typedef wchar_t WCHAR; // wc, 16-bit UNICODE character +typedef void *PVOID; +typedef CONST WCHAR *LPCWSTR, *PCWSTR; +typedef int BCRYPT_ALG_HANDLE; // using int as a placeholder +typedef long LONG; +typedef unsigned long ULONG; +typedef ULONG *PULONG; +typedef LONG NTSTATUS; +typedef ULONG_PTR HCRYPTHASH; +typedef ULONG_PTR HCRYPTPROV; +typedef ULONG_PTR HCRYPTKEY; +typedef ULONG_PTR HCRYPTHASH; +typedef unsigned int ALG_ID; +typedef unsigned int UINT; +typedef UINT UCHAR; +typedef UCHAR *PUCHAR; +typedef unsigned long long ULONGLONG; + + +#define BCRYPT_MD2_ALGORITHM L"MD2" +#define BCRYPT_MD4_ALGORITHM L"MD4" +#define BCRYPT_MD5_ALGORITHM L"MD5" +#define BCRYPT_SHA1_ALGORITHM L"SHA1" +#define BCRYPT_SHA256_ALGORITHM L"SHA256" +#define BCRYPT_SHA384_ALGORITHM L"SHA384" +#define BCRYPT_SHA512_ALGORITHM L"SHA512" + +#define NULL 0 + +int intgen(); + +NTSTATUS BCryptOpenAlgorithmProvider( + BCRYPT_ALG_HANDLE *phAlgorithm, + LPCWSTR pszAlgId, + LPCWSTR pszImplementation, + ULONG dwFlags) +{ + return intgen(); +} + + +NTSTATUS BCryptDeriveKeyPBKDF2( + BCRYPT_ALG_HANDLE hPrf, + PUCHAR pbPassword, + ULONG cbPassword, + PUCHAR pbSalt, + ULONG cbSalt, + ULONGLONG cIterations, + PUCHAR pbDerivedKey, + ULONG cbDerivedKey, + ULONG dwFlags) +{ + return intgen(); +} + +NTSTATUS BCryptCloseAlgorithmProvider( + BCRYPT_ALG_HANDLE hAlgorithm, + ULONG dwFlags +) +{ + return intgen(); +} \ No newline at end of file diff --git a/cpp/ql/test/query-tests/Microsoft/Security/Cryptography/WeakKDF/test.cpp b/cpp/ql/test/query-tests/Microsoft/Security/Cryptography/WeakKDF/test.cpp new file mode 100644 index 000000000000..85a114f14dc3 --- /dev/null +++ b/cpp/ql/test/query-tests/Microsoft/Security/Cryptography/WeakKDF/test.cpp @@ -0,0 +1,82 @@ + +#include "./bcrypt.h" +using namespace std; + +char* getString(); + +char* password = getString(); +char* salt = getString(); + +int strlen(char *s); + +void test_bad1() +{ + NTSTATUS Status; + BYTE DerivedKey[64]; + + BCRYPT_ALG_HANDLE handle; + // BAD hash algorithm handle generated here + Status = BCryptOpenAlgorithmProvider(&handle, BCRYPT_MD5_ALGORITHM, NULL, 0); + + if (Status != 0) + { + //std::cout << "BCryptOpenAlgorithmProvider exited with error message " << Status; + goto END; + } + + // BAD Hash algorithm handle + // BAD salt length + // BAD iteration count + // BAD Key length + Status = BCryptDeriveKeyPBKDF2(handle, (PUCHAR)password, strlen(password), (PUCHAR)salt, 8, 2048, (PUCHAR)DerivedKey, 8, 0); + //Status = BCryptDeriveKeyPBKDF2(handle, (PUCHAR)password.data(), password.length(), (PUCHAR)salt.data(), 8, 2048, (PUCHAR)DerivedKey, 64, 0); + + if (Status != 0) + { + //std::cout << "BCryptDeriveKeyPBKDF2 exited with error message " << Status; + goto END; + } + + //else + //std::cout << "Operation completed successfully. Your encrypted key is in variable DerivedKey."; + + BCryptCloseAlgorithmProvider(handle, 0); + +END:; +} + +void test_good1() +{ + NTSTATUS Status; + BYTE DerivedKey[64]; + + BCRYPT_ALG_HANDLE handle; + // GOOD hash handle generated here + Status = BCryptOpenAlgorithmProvider(&handle, BCRYPT_SHA256_ALGORITHM, NULL, 0); + + if (Status != 0) + { + //std::cout << "BCryptOpenAlgorithmProvider exited with error message " << Status; + goto END; + } + + // GOOD Hash algorithm handle + // GOOD salt length + // GOOD iteration count + // GOOD Key length + Status = BCryptDeriveKeyPBKDF2(handle, (PUCHAR)password, strlen(password), (PUCHAR)salt, 64, 100000, (PUCHAR)DerivedKey, 64, 0); + //Status = BCryptDeriveKeyPBKDF2(handle, (PUCHAR)password.data(), password.length(), (PUCHAR)salt.data(), 8, 2048, (PUCHAR)DerivedKey, 64, 0); + + if (Status != 0) + { + //std::cout << "BCryptDeriveKeyPBKDF2 exited with error message " << Status; + goto END; + } + + //else + //std::cout << "Operation completed successfully. Your encrypted key is in variable DerivedKey."; + + BCryptCloseAlgorithmProvider(handle, 0); + +END:; +} diff --git a/cpp/ql/test/query-tests/Microsoft/Security/MemoryAccess/EnumIndex/UncheckedBoundsEnumAsIndex.expected b/cpp/ql/test/query-tests/Microsoft/Security/MemoryAccess/EnumIndex/UncheckedBoundsEnumAsIndex.expected new file mode 100644 index 000000000000..267bf9720731 --- /dev/null +++ b/cpp/ql/test/query-tests/Microsoft/Security/MemoryAccess/EnumIndex/UncheckedBoundsEnumAsIndex.expected @@ -0,0 +1,4 @@ +| UncheckedBoundsEnumAsIndex_test.c:77:27:77:40 | CapabilityType | When accessing array PmiAcpiToCapabilities with index CapabilityType, the upper bound of an enum is used to check the upper bound of the array, but the lower bound is not checked. | +| UncheckedBoundsEnumAsIndex_test.c:111:31:111:44 | CapabilityType | When accessing array PmiAcpiToCapabilities with index CapabilityType, the upper bound of an enum is used to check the upper bound of the array, but the lower bound is not checked. | +| UncheckedBoundsEnumAsIndex_test.c:271:31:271:44 | CapabilityType | When accessing array PmiAcpiToCapabilities with index CapabilityType, the upper bound of an enum is used to check the upper bound of the array, but the lower bound is not checked. | +| UncheckedBoundsEnumAsIndex_test.c:293:31:293:44 | CapabilityType | When accessing array PmiAcpiToCapabilities with index CapabilityType, the upper bound of an enum is used to check the upper bound of the array, but the lower bound is not checked. | diff --git a/cpp/ql/test/query-tests/Microsoft/Security/MemoryAccess/EnumIndex/UncheckedBoundsEnumAsIndex.qlref b/cpp/ql/test/query-tests/Microsoft/Security/MemoryAccess/EnumIndex/UncheckedBoundsEnumAsIndex.qlref new file mode 100644 index 000000000000..ed446417bff7 --- /dev/null +++ b/cpp/ql/test/query-tests/Microsoft/Security/MemoryAccess/EnumIndex/UncheckedBoundsEnumAsIndex.qlref @@ -0,0 +1 @@ +Microsoft/Security/MemoryAccess/EnumIndex/UncheckedBoundsEnumAsIndex.ql \ No newline at end of file diff --git a/cpp/ql/test/query-tests/Microsoft/Security/MemoryAccess/EnumIndex/UncheckedBoundsEnumAsIndex_test.c b/cpp/ql/test/query-tests/Microsoft/Security/MemoryAccess/EnumIndex/UncheckedBoundsEnumAsIndex_test.c new file mode 100644 index 000000000000..7d919c14aedd --- /dev/null +++ b/cpp/ql/test/query-tests/Microsoft/Security/MemoryAccess/EnumIndex/UncheckedBoundsEnumAsIndex_test.c @@ -0,0 +1,299 @@ +typedef unsigned long ULONG; +typedef unsigned short USHORT; +typedef unsigned long DWORD; +typedef long NTSTATUS; +#define STATUS_INVALID_PARAMETER ((DWORD )0xC000000DL) + +typedef enum { + PmiMeasurementConfiguration, + PmiBudgetingConfiguration, + PmiThresholdConfiguration, + PmiConfigurationMax +} PMI_CONFIGURATION_TYPE; + +typedef struct _PMI_CONFIGURATION { + ULONG Version; + USHORT Size; + PMI_CONFIGURATION_TYPE ConfigurationType; +} PMI_CONFIGURATION, *PPMI_CONFIGURATION; + +typedef +NTSTATUS +PMI_CONFIGURATION_TO_ACPI( + ULONG something +); + +typedef +NTSTATUS +PMI_ACPI_TO_CAPABILITIES( + ULONG something +); + +typedef PMI_ACPI_TO_CAPABILITIES *PPMI_ACPI_TO_CAPABILITIES; + +NTSTATUS +AcpiPmipBuildReportedCapabilities( + ULONG something +) { + return 0; +} + +NTSTATUS +AcpiPmipBuildMeteredHardwareInformation( + ULONG something +) { + return 0; +} + +typedef enum { + PmiReportedCapabilities, + PmiMeteredHardware, + PmiCapabilitiesMax +} PMI_CAPABILITIES_TYPE; + +PPMI_ACPI_TO_CAPABILITIES PmiAcpiToCapabilities[PmiCapabilitiesMax] = { + AcpiPmipBuildReportedCapabilities, // PmiReportedCapabilities + AcpiPmipBuildMeteredHardwareInformation, // PmiMeteredHardware +}; + +typedef struct _PMI_CAPABILITIES { + ULONG Version; + ULONG Size; + PMI_CAPABILITIES_TYPE CapabilityType; +} PMI_CAPABILITIES, *PPMI_CAPABILITIES; + +NTSTATUS Test_NoLowerBoundCheckUsageAfterIfBlock(PPMI_CAPABILITIES PmiCapabilitiesInput) +{ + NTSTATUS Status = 0; + int CapabilityType; + + CapabilityType = PmiCapabilitiesInput->CapabilityType; + if (CapabilityType >= PmiCapabilitiesMax) + { + Status = STATUS_INVALID_PARAMETER; + goto IoctlGetCapabilitiesExit; + } + // ... + PmiAcpiToCapabilities[CapabilityType](0); // BUG + +IoctlGetCapabilitiesExit: + return Status; +} + +// If it fires == false positive +// unsigned type +NTSTATUS Test_NoLowerBoundCheckUsageAfterIfBlock_FP(PPMI_CAPABILITIES PmiCapabilitiesInput) +{ + NTSTATUS Status = 0; + PMI_CAPABILITIES_TYPE CapabilityType; + + CapabilityType = PmiCapabilitiesInput->CapabilityType; + if (CapabilityType >= PmiCapabilitiesMax) + { + Status = STATUS_INVALID_PARAMETER; + goto IoctlGetCapabilitiesExit; + } + // ... + PmiAcpiToCapabilities[CapabilityType](0); // NOT A BUG, CapabilityType is unsigned + +IoctlGetCapabilitiesExit: + return Status; +} + +NTSTATUS Test_NoLowerBoundCheckUsageWithinIfBlock(PPMI_CAPABILITIES PmiCapabilitiesInput) +{ + NTSTATUS Status = 0; + int CapabilityType; + + CapabilityType = PmiCapabilitiesInput->CapabilityType; + if (CapabilityType < PmiCapabilitiesMax) + { + PmiAcpiToCapabilities[CapabilityType](1); // BUG + } + else + { + Status = STATUS_INVALID_PARAMETER; + goto IoctlGetCapabilitiesExit; + } + // ... + +IoctlGetCapabilitiesExit: + return Status; +} + +// Should not fire an event as this doesn't meet the criteria +// CapabilityType is unsigned, so it will never be < 0 +// If it fires == false positive +NTSTATUS Test_NoLowerBoundCheckUsageWithinIfBlock_FP(PPMI_CAPABILITIES PmiCapabilitiesInput) +{ + NTSTATUS Status = 0; + PMI_CAPABILITIES_TYPE CapabilityType; + + CapabilityType = PmiCapabilitiesInput->CapabilityType; + if (CapabilityType < PmiCapabilitiesMax) + { + PmiAcpiToCapabilities[CapabilityType](1); // NOT A BUG, CapabilityType is unsigned + } + else + { + Status = STATUS_INVALID_PARAMETER; + goto IoctlGetCapabilitiesExit; + } + // ... + +IoctlGetCapabilitiesExit: + return Status; +} + +// Should not fire an event as this doesn't meet the criteria +// If it fires == false positive +NTSTATUS Test_NotMeetingUpperboundCheckCritieria(PPMI_CAPABILITIES PmiCapabilitiesInput) +{ + NTSTATUS Status = 0; + PMI_CAPABILITIES_TYPE CapabilityType; + + CapabilityType = PmiCapabilitiesInput->CapabilityType; + if (CapabilityType == PmiMeteredHardware) + { + PmiAcpiToCapabilities[CapabilityType](1); + } + else + { + Status = STATUS_INVALID_PARAMETER; + goto IoctlGetCapabilitiesExit; + } + // ... + +IoctlGetCapabilitiesExit: + return Status; +} + +// No bug - Correct Usage +NTSTATUS Test_CorrectUsage(PPMI_CAPABILITIES PmiCapabilitiesInput) +{ + NTSTATUS Status = 0; + DWORD x = 0; + PMI_CAPABILITIES_TYPE CapabilityType; + + CapabilityType = PmiCapabilitiesInput->CapabilityType; + if (CapabilityType < 0 || CapabilityType >= PmiCapabilitiesMax) + { + Status = STATUS_INVALID_PARAMETER; + goto IoctlGetCapabilitiesExit; + } + // ... + + x = 1; + + PmiAcpiToCapabilities[CapabilityType](2); + +IoctlGetCapabilitiesExit: + return Status; +} + +// No bug - Correct Usage +NTSTATUS Test_CorrectUsage2(PPMI_CAPABILITIES PmiCapabilitiesInput) +{ + NTSTATUS Status = 0; + DWORD x = 0; + int CapabilityType; + + CapabilityType = PmiCapabilitiesInput->CapabilityType; + if (CapabilityType < 0 || CapabilityType >= PmiCapabilitiesMax) + { + Status = STATUS_INVALID_PARAMETER; + goto IoctlGetCapabilitiesExit; + } + // ... + + x = 1; + + PmiAcpiToCapabilities[CapabilityType](2); + +IoctlGetCapabilitiesExit: + return Status; +} + +// Should not fire as the Guard is not an If statement. The for loop has an implicit lower bound +// If it fires == false positive +NTSTATUS Test_GuardIsNotAnIfStatement(PPMI_CAPABILITIES PmiCapabilitiesInput) +{ + NTSTATUS Status = 0; + DWORD x = 0; + int CapabilityType; + + for (CapabilityType = PmiReportedCapabilities; CapabilityType <= PmiCapabilitiesMax; CapabilityType++) + { + PmiAcpiToCapabilities[CapabilityType](2); + } + // ... + return Status; +} + + +// If it fires == false positive +NTSTATUS Test_GuardIsAnIfStatementButVariableLowerBound(PPMI_CAPABILITIES PmiCapabilitiesInput) +{ + NTSTATUS Status = 0; + DWORD x = 0; + int CapabilityType = 0; //==> Lower bound + + while (1) + { + if (CapabilityType >= PmiCapabilitiesMax) + { + break; + } + // ... + + PmiAcpiToCapabilities[CapabilityType](0); // NOT A BUG - Lower bound == 0 + // ... + CapabilityType++; + } + // ... + return Status; +} + +NTSTATUS Test_GuardIsAnIfStatementButVariableLowerBound_notbound(PPMI_CAPABILITIES PmiCapabilitiesInput, int initialBound) +{ + NTSTATUS Status = 0; + DWORD x = 0; + int CapabilityType = initialBound; //==> Lower bound + + while (1) + { + if (CapabilityType >= PmiCapabilitiesMax) + { + break; + } + // ... + + PmiAcpiToCapabilities[CapabilityType](0); //BUG - Lowerbound is unknown + // ... + CapabilityType++; + } + // ... + return Status; +} + +NTSTATUS Test_GuardIsAnIfStatementButVariableLowerBound_outofBounds(PPMI_CAPABILITIES PmiCapabilitiesInput) +{ + NTSTATUS Status = 0; + DWORD x = 0; + int CapabilityType = -1; //==> Lower bound + + while (1) + { + if (CapabilityType >= PmiCapabilitiesMax) + { + break; + } + // ... + + PmiAcpiToCapabilities[CapabilityType](0); // BUG - lower bound is < 0 + // ... + CapabilityType++; + } + // ... + return Status; +} diff --git a/cpp/ql/test/query-tests/Microsoft/Security/Protocols/default/HardCodedSecurityProtocol.expected b/cpp/ql/test/query-tests/Microsoft/Security/Protocols/default/HardCodedSecurityProtocol.expected new file mode 100644 index 000000000000..9e2c180bba95 --- /dev/null +++ b/cpp/ql/test/query-tests/Microsoft/Security/Protocols/default/HardCodedSecurityProtocol.expected @@ -0,0 +1,10 @@ +| test.cpp:50:43:50:61 | 1 | Hard-coded use of security protocol SP_PROT_PCT1_SERVER set here $@. | test.cpp:50:43:50:61 | 1 | 1 | +| test.cpp:51:43:51:61 | 4 | Hard-coded use of security protocol SP_PROT_SSL2_SERVER set here $@. | test.cpp:51:43:51:61 | 4 | 4 | +| test.cpp:52:43:52:61 | 16 | Hard-coded use of security protocol SP_PROT_SSL3_SERVER set here $@. | test.cpp:52:43:52:61 | 16 | 16 | +| test.cpp:53:43:53:56 | ... \| ... | Hard-coded use of security protocol SP_PROT_TLS1_1 set here $@. | test.cpp:53:43:53:56 | ... \| ... | ... \| ... | +| test.cpp:54:44:54:88 | ... \| ... | Hard-coded use of security protocol ... \| ... set here $@. | test.cpp:54:43:54:89 | ... \| ... | ... \| ... | +| test.cpp:55:43:55:58 | ... \| ... | Hard-coded use of security protocol SP_PROT_SSL3TLS1 set here $@. | test.cpp:55:43:55:58 | ... \| ... | ... \| ... | +| test.cpp:56:54:56:74 | 256 | Hard-coded use of security protocol SP_PROT_TLS1_1_SERVER set here $@. | test.cpp:56:43:56:98 | ... ? ... : ... | ... ? ... : ... | +| test.cpp:56:78:56:98 | 512 | Hard-coded use of security protocol SP_PROT_TLS1_1_CLIENT set here $@. | test.cpp:56:43:56:98 | ... ? ... : ... | ... ? ... : ... | +| test.cpp:58:43:58:56 | ... \| ... | Hard-coded use of security protocol SP_PROT_TLS1_2 set here $@. | test.cpp:58:43:58:56 | ... \| ... | ... \| ... | +| test.cpp:59:43:59:56 | ... \| ... | Hard-coded use of security protocol SP_PROT_TLS1_3 set here $@. | test.cpp:59:43:59:56 | ... \| ... | ... \| ... | diff --git a/cpp/ql/test/query-tests/Microsoft/Security/Protocols/default/HardCodedSecurityProtocol.qlref b/cpp/ql/test/query-tests/Microsoft/Security/Protocols/default/HardCodedSecurityProtocol.qlref new file mode 100644 index 000000000000..a1a61b133f34 --- /dev/null +++ b/cpp/ql/test/query-tests/Microsoft/Security/Protocols/default/HardCodedSecurityProtocol.qlref @@ -0,0 +1 @@ +Microsoft/Security/Protocols/HardCodedSecurityProtocol.ql \ No newline at end of file diff --git a/cpp/ql/test/query-tests/Microsoft/Security/Protocols/default/UseOfDeprecatedSecurityProtocol.expected b/cpp/ql/test/query-tests/Microsoft/Security/Protocols/default/UseOfDeprecatedSecurityProtocol.expected new file mode 100644 index 000000000000..337e2630cb81 --- /dev/null +++ b/cpp/ql/test/query-tests/Microsoft/Security/Protocols/default/UseOfDeprecatedSecurityProtocol.expected @@ -0,0 +1,8 @@ +| test.cpp:50:43:50:61 | 1 | Hard-coded use of deprecated security protocol SP_PROT_PCT1_SERVER set here $@. | test.cpp:50:43:50:61 | 1 | SP_PROT_PCT1_SERVER | +| test.cpp:51:43:51:61 | 4 | Hard-coded use of deprecated security protocol SP_PROT_SSL2_SERVER set here $@. | test.cpp:51:43:51:61 | 4 | SP_PROT_SSL2_SERVER | +| test.cpp:52:43:52:61 | 16 | Hard-coded use of deprecated security protocol SP_PROT_SSL3_SERVER set here $@. | test.cpp:52:43:52:61 | 16 | SP_PROT_SSL3_SERVER | +| test.cpp:53:43:53:56 | ... \| ... | Hard-coded use of deprecated security protocol SP_PROT_TLS1_1 set here $@. | test.cpp:53:43:53:56 | ... \| ... | SP_PROT_TLS1_1 | +| test.cpp:54:44:54:88 | ... \| ... | Hard-coded use of deprecated security protocol ... \| ... set here $@. | test.cpp:54:44:54:88 | ... \| ... | ... \| ... | +| test.cpp:55:43:55:58 | ... \| ... | Hard-coded use of deprecated security protocol SP_PROT_SSL3TLS1 set here $@. | test.cpp:55:43:55:58 | ... \| ... | SP_PROT_SSL3TLS1 | +| test.cpp:56:54:56:74 | 256 | Hard-coded use of deprecated security protocol SP_PROT_TLS1_1_SERVER set here $@. | test.cpp:56:54:56:74 | 256 | SP_PROT_TLS1_1_SERVER | +| test.cpp:56:78:56:98 | 512 | Hard-coded use of deprecated security protocol SP_PROT_TLS1_1_CLIENT set here $@. | test.cpp:56:78:56:98 | 512 | SP_PROT_TLS1_1_CLIENT | diff --git a/cpp/ql/test/query-tests/Microsoft/Security/Protocols/default/UseOfDeprecatedSecurityProtocol.qlref b/cpp/ql/test/query-tests/Microsoft/Security/Protocols/default/UseOfDeprecatedSecurityProtocol.qlref new file mode 100644 index 000000000000..18e939dd1bed --- /dev/null +++ b/cpp/ql/test/query-tests/Microsoft/Security/Protocols/default/UseOfDeprecatedSecurityProtocol.qlref @@ -0,0 +1 @@ +Microsoft/Security/Protocols/UseOfDeprecatedSecurityProtocol.ql \ No newline at end of file diff --git a/cpp/ql/test/query-tests/Microsoft/Security/Protocols/default/test.cpp b/cpp/ql/test/query-tests/Microsoft/Security/Protocols/default/test.cpp new file mode 100644 index 000000000000..d34bc3599180 --- /dev/null +++ b/cpp/ql/test/query-tests/Microsoft/Security/Protocols/default/test.cpp @@ -0,0 +1,65 @@ +// semmle-extractor-options: --microsoft + +typedef unsigned long DWORD; + +typedef struct _SCHANNEL_CRED { + // Note: Fields removed before/after to avoid needing to include headers for field types + DWORD grbitEnabledProtocols; +} SCHANNEL_CRED, *PSCHANNEL_CRED; + +#define SP_PROT_PCT1_SERVER 0x00000001 +#define SP_PROT_PCT1_CLIENT 0x00000002 +#define SP_PROT_PCT1 (SP_PROT_PCT1_SERVER | SP_PROT_PCT1_CLIENT) + +#define SP_PROT_SSL2_SERVER 0x00000004 +#define SP_PROT_SSL2_CLIENT 0x00000008 +#define SP_PROT_SSL2 (SP_PROT_SSL2_SERVER | SP_PROT_SSL2_CLIENT) + +#define SP_PROT_SSL3_SERVER 0x00000010 +#define SP_PROT_SSL3_CLIENT 0x00000020 +#define SP_PROT_SSL3 (SP_PROT_SSL3_SERVER | SP_PROT_SSL3_CLIENT) + +#define SP_PROT_TLS1_SERVER 0x00000040 +#define SP_PROT_TLS1_CLIENT 0x00000080 +#define SP_PROT_TLS1 (SP_PROT_TLS1_SERVER | SP_PROT_TLS1_CLIENT) + +#define SP_PROT_TLS1_0_SERVER SP_PROT_TLS1_SERVER +#define SP_PROT_TLS1_0_CLIENT SP_PROT_TLS1_CLIENT +#define SP_PROT_TLS1_0 (SP_PROT_TLS1_0_SERVER | \ + SP_PROT_TLS1_0_CLIENT) + +#define SP_PROT_TLS1_1_SERVER 0x00000100 +#define SP_PROT_TLS1_1_CLIENT 0x00000200 +#define SP_PROT_TLS1_1 (SP_PROT_TLS1_1_SERVER | SP_PROT_TLS1_1_CLIENT) + +#define SP_PROT_SSL3TLS1_CLIENTS (SP_PROT_TLS1_CLIENT | SP_PROT_SSL3_CLIENT) +#define SP_PROT_SSL3TLS1_SERVERS (SP_PROT_TLS1_SERVER | SP_PROT_SSL3_SERVER) +#define SP_PROT_SSL3TLS1 (SP_PROT_SSL3 | SP_PROT_TLS1) + +#define SP_PROT_TLS1_2_SERVER 0x00000400 +#define SP_PROT_TLS1_2_CLIENT 0x00000800 +#define SP_PROT_TLS1_2 (SP_PROT_TLS1_2_SERVER | SP_PROT_TLS1_2_CLIENT) + +#define SP_PROT_TLS1_3_SERVER 0x00001000 +#define SP_PROT_TLS1_3_CLIENT 0x00002000 +#define SP_PROT_TLS1_3 (SP_PROT_TLS1_3_SERVER | SP_PROT_TLS1_3_CLIENT) + +void testProtocols(bool isServer, DWORD cred) { + SCHANNEL_CRED testSChannelCred; + // BAD: Deprecated protocols + testSChannelCred.grbitEnabledProtocols = SP_PROT_PCT1_SERVER; + testSChannelCred.grbitEnabledProtocols = SP_PROT_SSL2_SERVER; + testSChannelCred.grbitEnabledProtocols = SP_PROT_SSL3_SERVER; + testSChannelCred.grbitEnabledProtocols = SP_PROT_TLS1_1; + testSChannelCred.grbitEnabledProtocols = (SP_PROT_TLS1_1_SERVER | SP_PROT_TLS1_1_CLIENT); + testSChannelCred.grbitEnabledProtocols = SP_PROT_SSL3TLS1; + testSChannelCred.grbitEnabledProtocols = isServer ? SP_PROT_TLS1_1_SERVER : SP_PROT_TLS1_1_CLIENT; + // BAD: hardcoded, but not deprecated, protocol + testSChannelCred.grbitEnabledProtocols = SP_PROT_TLS1_2; + testSChannelCred.grbitEnabledProtocols = SP_PROT_TLS1_3; + // GOOD: system default protocol + testSChannelCred.grbitEnabledProtocols = 0; + // UNKNOWN: Do not flag SP_PROT_TLS1_1 here + // We do not know anything about cred, so don't flag it + testSChannelCred.grbitEnabledProtocols = cred & ~SP_PROT_TLS1_1; +}