Skip to content

Commit df01fa7

Browse files
committed
Expand model and JCA modeling
1 parent b777a22 commit df01fa7

File tree

3 files changed

+237
-42
lines changed
  • java/ql
  • shared/cryptography/codeql/cryptography

3 files changed

+237
-42
lines changed

java/ql/lib/experimental/Quantum/JCA.qll

Lines changed: 135 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,8 @@ module JCAModel {
5454
}
5555

5656
Expr getAlgorithmArg() { result = this.getArgument(0) }
57+
58+
Expr getProviderArg() { result = this.getArgument(1) }
5759
}
5860

5961
/**
@@ -75,7 +77,7 @@ module JCAModel {
7577
* For example, in `Cipher.getInstance(algorithm)`, this class represents `algorithm`.
7678
*/
7779
class CipherGetInstanceAlgorithmArg extends Crypto::EncryptionAlgorithmInstance,
78-
Crypto::ModeOfOperationAlgorithmInstance instanceof Expr
80+
Crypto::ModeOfOperationAlgorithmInstance, Crypto::PaddingAlgorithmInstance instanceof Expr
7981
{
8082
CipherGetInstanceAlgorithmArg() {
8183
exists(CipherGetInstanceCall call | this = call.getArgument(0))
@@ -114,14 +116,62 @@ module JCAModel {
114116

115117
override Location getLocation() { result = instance.getLocation() }
116118

117-
override string getRawAlgorithmName() { result = instance.getOrigin().getValue() }
119+
// In this case, the raw name is still only the /MODE/ part.
120+
// TODO: handle defaults
121+
override string getRawAlgorithmName() { result = instance.getOrigin().getMode() }
118122

119-
predicate modeToNameMapping(Crypto::TModeOperationType type, string name) {
120-
super.modeToNameMapping(type, name)
123+
private predicate modeToNameMappingKnown(Crypto::TModeOperationType type, string name) {
124+
type instanceof Crypto::ECB and name = "ECB"
125+
or
126+
type instanceof Crypto::CBC and name = "CBC"
127+
or
128+
type instanceof Crypto::GCM and name = "GCM"
129+
or
130+
type instanceof Crypto::CTR and name = "CTR"
131+
or
132+
type instanceof Crypto::XTS and name = "XTS"
133+
or
134+
type instanceof Crypto::CCM and name = "CCM"
135+
or
136+
type instanceof Crypto::SIV and name = "SIV"
137+
or
138+
type instanceof Crypto::OCB and name = "OCB"
121139
}
122140

123141
override Crypto::TModeOperationType getModeType() {
124-
this.modeToNameMapping(result, instance.getOrigin().getMode())
142+
if this.modeToNameMappingKnown(_, instance.getOrigin().getMode())
143+
then this.modeToNameMappingKnown(result, instance.getOrigin().getMode())
144+
else result instanceof Crypto::OtherMode
145+
}
146+
147+
CipherStringLiteral getInstance() { result = instance }
148+
}
149+
150+
class PaddingAlgorithm extends Crypto::PaddingAlgorithm {
151+
CipherGetInstanceAlgorithmArg instance;
152+
153+
PaddingAlgorithm() {
154+
this = Crypto::TPaddingAlgorithm(instance) and
155+
exists(instance.getOrigin().getPadding())
156+
}
157+
158+
override Location getLocation() { result = instance.getLocation() }
159+
160+
override string getRawAlgorithmName() { result = instance.getOrigin().getPadding() }
161+
162+
bindingset[name]
163+
private predicate paddingToNameMappingKnown(Crypto::TPaddingType type, string name) {
164+
type instanceof Crypto::NoPadding and name = "NOPADDING"
165+
or
166+
type instanceof Crypto::PKCS7 and name = ["PKCS5Padding", "PKCS7Padding"] // TODO: misnomer in the JCA?
167+
or
168+
type instanceof Crypto::OAEP and name.matches("OAEP%") // TODO: handle OAEPWith%
169+
}
170+
171+
override Crypto::TPaddingType getPaddingType() {
172+
if this.paddingToNameMappingKnown(_, instance.getOrigin().getPadding())
173+
then this.paddingToNameMappingKnown(result, instance.getOrigin().getPadding())
174+
else result instanceof Crypto::OtherPadding
125175
}
126176

127177
CipherStringLiteral getInstance() { result = instance }
@@ -142,14 +192,20 @@ module JCAModel {
142192
result.(ModeOfOperation).getInstance() = origin
143193
}
144194

195+
override Crypto::PaddingAlgorithm getPadding() {
196+
result.(PaddingAlgorithm).getInstance() = origin
197+
}
198+
145199
override Crypto::LocatableElement getOrigin(string name) {
146200
result = origin and name = origin.toString()
147201
}
148202

149203
override string getRawAlgorithmName() { result = origin.getValue() }
150204

151205
override Crypto::TCipherType getCipherFamily() {
152-
this.cipherNameMapping(result, origin.getAlgorithmName())
206+
if this.cipherNameMappingKnown(_, origin.getAlgorithmName())
207+
then this.cipherNameMappingKnown(result, origin.getAlgorithmName())
208+
else result instanceof Crypto::OtherSymmetricCipherType
153209
}
154210

155211
override string getKeySize(Location location) { none() }
@@ -159,18 +215,83 @@ module JCAModel {
159215
name = "AES" and
160216
type instanceof Crypto::AES
161217
or
218+
name = "DES" and
219+
type instanceof Crypto::DES
220+
or
221+
name = "TripleDES" and
222+
type instanceof Crypto::TripleDES
223+
or
224+
name = "IDEA" and
225+
type instanceof Crypto::IDEA
226+
or
227+
name = "CAST5" and
228+
type instanceof Crypto::CAST5
229+
or
230+
name = "ChaCha20" and
231+
type instanceof Crypto::ChaCha20
232+
or
162233
name = "RC4" and
163234
type instanceof Crypto::RC4
164-
// or
165-
// TODO
235+
or
236+
name = "RC5" and
237+
type instanceof Crypto::RC5
238+
or
239+
name = "RSA" and
240+
type instanceof Crypto::RSA
166241
}
242+
}
167243

168-
bindingset[name]
169-
predicate cipherNameMapping(Crypto::TCipherType type, string name) {
170-
this.cipherNameMappingKnown(type, name)
171-
or
172-
not this.cipherNameMappingKnown(_, name) and
173-
type instanceof Crypto::OtherSymmetricCipherType
244+
/**
245+
* Initialiation vectors
246+
*/
247+
abstract class IVParameterInstantiation extends ClassInstanceExpr {
248+
abstract Expr getIV();
249+
}
250+
251+
class IvParameterSpecInstance extends IVParameterInstantiation {
252+
IvParameterSpecInstance() {
253+
this.getConstructedType().hasQualifiedName("javax.crypto.spec", "IvParameterSpec")
254+
}
255+
256+
override Expr getIV() { result = super.getArgument(0) }
257+
}
258+
259+
class GCMParameterSpecInstance extends IVParameterInstantiation {
260+
GCMParameterSpecInstance() {
261+
this.getConstructedType().hasQualifiedName("javax.crypto.spec", "GCMParameterSpec")
174262
}
263+
264+
override Expr getIV() { result = super.getArgument(1) }
265+
}
266+
267+
class CipherInitCall extends MethodCall {
268+
CipherInitCall() { this.getCallee().hasQualifiedName("javax.crypto", "Cipher", "init") }
269+
270+
Expr getModeArg() { result = this.getArgument(0) }
271+
272+
Expr getKey() {
273+
result = this.getArgument(1) and this.getMethod().getParameterType(1).hasName("Key")
274+
}
275+
276+
Expr getIV() {
277+
result = this.getArgument(2) and
278+
this.getMethod().getParameterType(2).hasName("AlgorithmParameterSpec")
279+
}
280+
}
281+
282+
// TODO: cipher.getParameters().getParameterSpec(GCMParameterSpec.class);
283+
class InitializationVectorExpr extends Crypto::InitializationVectorArtifactInstance instanceof Expr
284+
{
285+
CipherInitCall call; // TODO: add origin to known sources (e.g. RNG, etc.)
286+
287+
InitializationVectorExpr() { this = call.getIV() }
288+
}
289+
290+
class InitializationVector extends Crypto::InitializationVector {
291+
InitializationVectorExpr instance;
292+
293+
InitializationVector() { this = Crypto::TInitializationVector(instance) }
294+
295+
override Location getLocation() { result = instance.getLocation() }
175296
}
176297
}

java/ql/src/experimental/Quantum/Test.ql

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,6 @@
44

55
import experimental.Quantum.Language
66

7-
from Crypto::EncryptionAlgorithm a, Crypto::ModeOfOperationAlgorithm mode
8-
where a.getModeOfOperation() = mode
9-
select a, a.getAlgorithmName(), a.getRawAlgorithmName(), mode, mode.getAlgorithmName()
7+
from Crypto::EncryptionAlgorithm a, Crypto::ModeOfOperationAlgorithm m, Crypto::PaddingAlgorithm p
8+
where m = a.getModeOfOperation() and p = a.getPadding()
9+
select a, a.getRawAlgorithmName(), m, m.getRawAlgorithmName(), p, p.getRawAlgorithmName()

0 commit comments

Comments
 (0)