1
+ /**
2
+ * A language-independent library for reasoning about cryptography.
3
+ */
4
+
5
+ import codeql.util.Location
6
+ import codeql.util.Option
7
+
8
+ signature module InputSig< LocationSig Location> {
9
+ class LocatableElement {
10
+ Location getLocation ( ) ;
11
+ }
12
+
13
+ class UnknownLocation instanceof Location ;
14
+ }
15
+
16
+ module CryptographyBase< LocationSig Location, InputSig< Location > Input> {
17
+ final class LocatableElement = Input:: LocatableElement ;
18
+
19
+ final class UnknownLocation = Input:: UnknownLocation ;
20
+
21
+ final class UnknownPropertyValue extends string {
22
+ UnknownPropertyValue ( ) { this = "<unknown>" }
23
+ }
24
+
25
+ abstract class NodeBase instanceof LocatableElement {
26
+ /**
27
+ * Returns a string representation of this node, usually the name of the operation/algorithm/property.
28
+ */
29
+ abstract string toString ( ) ;
30
+
31
+ /**
32
+ * Returns the location of this node in the code.
33
+ */
34
+ Location getLocation ( ) { result = super .getLocation ( ) }
35
+
36
+ /**
37
+ * Gets the origin of this node, e.g., a string literal in source describing it.
38
+ */
39
+ LocatableElement getOrigin ( string value ) { none ( ) }
40
+
41
+ /**
42
+ * Returns the child of this node with the given edge name.
43
+ *
44
+ * This predicate is used by derived classes to construct the graph of cryptographic operations.
45
+ */
46
+ NodeBase getChild ( string edgeName ) { none ( ) }
47
+
48
+ /**
49
+ * Defines properties of this node by name and either a value or location or both.
50
+ *
51
+ * This predicate is used by derived classes to construct the graph of cryptographic operations.
52
+ */
53
+ predicate properties ( string key , string value , Location location ) {
54
+ key = "origin" and location = this .getOrigin ( value ) .getLocation ( )
55
+ }
56
+
57
+ /**
58
+ * Returns the parent of this node.
59
+ */
60
+ final NodeBase getAParent ( ) { result .getChild ( _) = this }
61
+ }
62
+
63
+ class Asset = NodeBase ;
64
+
65
+ /**
66
+ * A cryptographic operation, such as hashing or encryption.
67
+ */
68
+ abstract class Operation extends Asset {
69
+ /**
70
+ * Gets the algorithm associated with this operation.
71
+ */
72
+ abstract Algorithm getAlgorithm ( ) ;
73
+
74
+ /**
75
+ * Gets the name of this operation, e.g., "hash" or "encrypt".
76
+ */
77
+ abstract string getOperationName ( ) ;
78
+
79
+ final override string toString ( ) { result = this .getOperationName ( ) }
80
+
81
+ override NodeBase getChild ( string edgeName ) {
82
+ result = super .getChild ( edgeName )
83
+ or
84
+ edgeName = "uses" and
85
+ if exists ( this .getAlgorithm ( ) ) then result = this .getAlgorithm ( ) else result = this
86
+ }
87
+ }
88
+
89
+ abstract class Algorithm extends Asset {
90
+ /**
91
+ * Gets the name of this algorithm, e.g., "AES" or "SHA".
92
+ */
93
+ abstract string getAlgorithmName ( ) ;
94
+
95
+ final override string toString ( ) { result = this .getAlgorithmName ( ) }
96
+ }
97
+
98
+ /**
99
+ * A hashing operation that processes data to generate a hash value.
100
+ * This operation takes an input message of arbitrary content and length and produces a fixed-size
101
+ * hash value as the output using a specified hashing algorithm.
102
+ */
103
+ abstract class HashOperation extends Operation {
104
+ abstract override HashAlgorithm getAlgorithm ( ) ;
105
+
106
+ override string getOperationName ( ) { result = "HASH" }
107
+ }
108
+
109
+ // Rule: no newtype representing a type of algorithm should be modelled with multiple interfaces
110
+ //
111
+ // Example: HKDF and PKCS12KDF are both key derivation algorithms.
112
+ // However, PKCS12KDF also has a property: the iteration count.
113
+ //
114
+ // If we have HKDF and PKCS12KDF under TKeyDerivationType,
115
+ // someone modelling a library might try to make a generic identification of both of those algorithms.
116
+ //
117
+ // They will therefore not use the specialized type for PKCS12KDF,
118
+ // meaning "from PKCS12KDF algo select algo" will have no results.
119
+ //
120
+ newtype THashType =
121
+ // We're saying by this that all of these have an identical interface / properties / edges
122
+ MD5 ( ) or
123
+ SHA1 ( ) or
124
+ SHA256 ( ) or
125
+ SHA512 ( ) or
126
+ OtherHashType ( )
127
+
128
+ /**
129
+ * A hashing algorithm that transforms variable-length input into a fixed-size hash value.
130
+ */
131
+ abstract class HashAlgorithm extends Algorithm {
132
+ final predicate hashTypeToNameMapping ( THashType type , string name ) {
133
+ type instanceof MD5 and name = "MD5"
134
+ or
135
+ type instanceof SHA1 and name = "SHA-1"
136
+ or
137
+ type instanceof SHA256 and name = "SHA-256"
138
+ or
139
+ type instanceof SHA512 and name = "SHA-512"
140
+ or
141
+ type instanceof OtherHashType and name = this .getRawAlgorithmName ( )
142
+ }
143
+
144
+ abstract THashType getHashType ( ) ;
145
+
146
+ override string getAlgorithmName ( ) { this .hashTypeToNameMapping ( this .getHashType ( ) , result ) }
147
+
148
+ /**
149
+ * Gets the raw name of this hash algorithm from source.
150
+ */
151
+ abstract string getRawAlgorithmName ( ) ;
152
+ }
153
+
154
+ /**
155
+ * An operation that derives one or more keys from an input value.
156
+ */
157
+ abstract class KeyDerivationOperation extends Operation {
158
+ override string getOperationName ( ) { result = "KEY_DERIVATION" }
159
+ }
160
+
161
+ /**
162
+ * An algorithm that derives one or more keys from an input value.
163
+ */
164
+ abstract class KeyDerivationAlgorithm extends Algorithm {
165
+ abstract override string getAlgorithmName ( ) ;
166
+ }
167
+
168
+ /**
169
+ * HKDF key derivation function
170
+ */
171
+ abstract class HKDF extends KeyDerivationAlgorithm {
172
+ final override string getAlgorithmName ( ) { result = "HKDF" }
173
+
174
+ abstract HashAlgorithm getHashAlgorithm ( ) ;
175
+
176
+ override NodeBase getChild ( string edgeName ) {
177
+ result = super .getChild ( edgeName )
178
+ or
179
+ edgeName = "digest" and result = this .getHashAlgorithm ( )
180
+ }
181
+ }
182
+
183
+ /**
184
+ * PKCS #12 key derivation function
185
+ */
186
+ abstract class PKCS12KDF extends KeyDerivationAlgorithm {
187
+ final override string getAlgorithmName ( ) { result = "PKCS12KDF" }
188
+
189
+ abstract HashAlgorithm getHashAlgorithm ( ) ;
190
+
191
+ override NodeBase getChild ( string edgeName ) {
192
+ result = super .getChild ( edgeName )
193
+ or
194
+ edgeName = "digest" and result = this .getHashAlgorithm ( )
195
+ }
196
+ }
197
+
198
+ /**
199
+ * Elliptic curve algorithm
200
+ */
201
+ abstract class EllipticCurve extends Algorithm {
202
+ abstract string getVersion ( Location location ) ;
203
+
204
+ abstract string getKeySize ( Location location ) ;
205
+
206
+ override predicate properties ( string key , string value , Location location ) {
207
+ super .properties ( key , value , location )
208
+ or
209
+ key = "version" and
210
+ if exists ( this .getVersion ( location ) )
211
+ then value = this .getVersion ( location )
212
+ else (
213
+ value instanceof UnknownPropertyValue and location instanceof UnknownLocation
214
+ )
215
+ or
216
+ key = "key_size" and
217
+ if exists ( this .getKeySize ( location ) )
218
+ then value = this .getKeySize ( location )
219
+ else (
220
+ value instanceof UnknownPropertyValue and location instanceof UnknownLocation
221
+ )
222
+ }
223
+ }
224
+
225
+ /**
226
+ * An encryption operation that processes plaintext to generate a ciphertext.
227
+ * This operation takes an input message (plaintext) of arbitrary content and length and produces a ciphertext as the output using a specified encryption algorithm (with a mode and padding).
228
+ */
229
+ abstract class EncryptionOperation extends Operation {
230
+ abstract override Algorithm getAlgorithm ( ) ;
231
+
232
+ override string getOperationName ( ) { result = "ENCRYPTION" }
233
+ }
234
+ }
235
+
0 commit comments