-
Notifications
You must be signed in to change notification settings - Fork 2k
Expand file tree
/
Copy pathArgon2CffiModule.qll
More file actions
137 lines (107 loc) · 4.64 KB
/
Argon2CffiModule.qll
File metadata and controls
137 lines (107 loc) · 4.64 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
import python
import semmle.python.ApiGraphs
import experimental.cryptography.CryptoArtifact
import experimental.cryptography.CryptoAlgorithmNames
import experimental.cryptography.utils.CallCfgNodeWithTarget
private import experimental.cryptography.utils.Utils as Utils
/**
* Provides models for the `argon2-cffi` PyPI package.
* See https://argon2-cffi.readthedocs.io/en/stable/.
*/
module Argon2Cffi {
API::CallNode getAPasswordHasher() {
result = API::moduleImport("argon2")
.getMember("PasswordHasher")
.getACall()
}
DataFlow::LocalSourceNode getAnArgonType(string fullName, string member) {
result = API::moduleImport("argon2")
.getMember("low_level")
.getMember("Type")
.getMember(member)
.asSource()
and (
(fullName = "ARGON2D" and member = "D")
or
(fullName = "ARGON2I" and member = "I")
or
(fullName = "ARGON2ID" and member = "ID")
)
}
class ArgonType extends DataFlow::LocalSourceNode {
ArgonType() { this = getAnArgonType(_, _) }
string getName() { this = getAnArgonType(result, _) }
}
// note: password hashers instantiated using `from_parameters` are not modelled (yet)
class PasswordHasher extends KeyDerivationAlgorithm {
PasswordHasher() { this = getAPasswordHasher() }
API::Node getTypeParameter() {
result = this.(API::CallNode).getParameter(6, "type")
}
override string getName() {
if exists(this.getTypeParameter()) then exists(
ArgonType type | type.flowsTo(this.getTypeParameter().asSink()) | result = type.getName()
)
else result = "ARGON2ID"
}
}
abstract class PasswordHasherOperation extends KeyDerivationOperation {
PasswordHasher instance;
PasswordHasherOperation() {
this = instance.(API::CallNode).getAMethodCall(["hash", "verify"])
}
override PasswordHasher getAlgorithm() { result = instance }
override DataFlow::Node getInitialisation() { result = instance }
override predicate requiresHash() { none() }
override predicate requiresMode() { none() }
// although Argon is salted, the salt parameter is optional as the library generates one for you
override predicate requiresSalt() { none() }
override predicate requiresIteration() { none() }
override predicate requiresLanes() { none() }
override predicate requiresMemoryCost() { none() }
override DataFlow::Node getSaltConfigSink() {
result = this.getSaltConfigSink(_)
}
private DataFlow::Node getSaltConfigSink(API::Node apiNode) {
result = apiNode.asSink() and
apiNode = this.(API::CallNode).getKeywordParameter("salt")
}
override DataFlow::Node getSaltConfigSrc() {
result = this.getSaltConfigSrc(_)
}
private DataFlow::Node getSaltConfigSrc(API::Node apiNode) {
exists(this.getSaltConfigSink(apiNode)) and
result = Utils::getUltimateSrcFromApiNode(apiNode)
}
override DataFlow::Node getHashConfigSrc() { none() }
override DataFlow::Node getIterationSizeSrc() {
result = Utils::getUltimateSrcFromApiNode(instance.(API::CallNode).getParameter(0, "time_cost"))
}
override DataFlow::Node getMemoryCostConfigSrc() {
result = Utils::getUltimateSrcFromApiNode(instance.(API::CallNode).getParameter(1, "memory_cost"))
}
override DataFlow::Node getLanesConfigSrc() {
result = Utils::getUltimateSrcFromApiNode(instance.(API::CallNode).getParameter(2, "parallelism"))
}
override DataFlow::Node getDerivedKeySizeSrc() {
result = Utils::getUltimateSrcFromApiNode(instance.(API::CallNode).getParameter(3, "hash_len"))
}
override DataFlow::Node getModeSrc() { none() }
}
class HashOperation extends PasswordHasherOperation {
HashOperation() {
this = instance.(API::CallNode).getAMethodCall("hash")
}
override DataFlow::Node getAnInput() {
result = this.(API::CallNode).getArg(0) or result = this.(API::CallNode).getArgByName("password")
}
}
class VerifyOperation extends PasswordHasherOperation {
VerifyOperation() {
this = instance.(API::CallNode).getAMethodCall("verify")
}
override DataFlow::Node getAnInput() {
result = this.(API::CallNode).getArg(1) or result = this.(API::CallNode).getArgByName("password")
}
}
}