Skip to content

Commit 8f36624

Browse files
committed
Add AsymmetricAlgorithmNode, refactor and address feedback
1 parent ab3f62e commit 8f36624

File tree

5 files changed

+83
-59
lines changed

5 files changed

+83
-59
lines changed

java/ql/lib/experimental/quantum/Language.qll

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -42,19 +42,15 @@ module CryptoInput implements InputSig<Language::Location> {
4242
}
4343
}
4444

45-
/**
46-
* Instantiate the model
47-
*/
45+
// Instantiate the `CryptographyBase` module
4846
module Crypto = CryptographyBase<Language::Location, CryptoInput>;
4947

50-
/**
51-
* Definitions of various generic data sources
52-
*/
48+
// Definitions of various generic sources
5349
final class DefaultFlowSource = SourceNode;
5450

5551
final class DefaultRemoteFlowSource = RemoteFlowSource;
5652

57-
class GenericUnreferencedParameterSource extends Crypto::GenericUnreferencedParameterSource {
53+
private class GenericUnreferencedParameterSource extends Crypto::GenericUnreferencedParameterSource {
5854
GenericUnreferencedParameterSource() {
5955
exists(Parameter p | this = p and not exists(p.getAnArgument()))
6056
}
@@ -68,7 +64,7 @@ class GenericUnreferencedParameterSource extends Crypto::GenericUnreferencedPara
6864
override string getAdditionalDescription() { result = this.toString() }
6965
}
7066

71-
class GenericLocalDataSource extends Crypto::GenericLocalDataSource {
67+
private class GenericLocalDataSource extends Crypto::GenericLocalDataSource {
7268
GenericLocalDataSource() {
7369
any(DefaultFlowSource src | not src instanceof DefaultRemoteFlowSource).asExpr() = this
7470
}
@@ -82,7 +78,7 @@ class GenericLocalDataSource extends Crypto::GenericLocalDataSource {
8278
override string getAdditionalDescription() { result = this.toString() }
8379
}
8480

85-
class GenericRemoteDataSource extends Crypto::GenericRemoteDataSource {
81+
private class GenericRemoteDataSource extends Crypto::GenericRemoteDataSource {
8682
GenericRemoteDataSource() { any(DefaultRemoteFlowSource src).asExpr() = this }
8783

8884
override DataFlow::Node getOutputNode() { result.asExpr() = this }
@@ -94,7 +90,7 @@ class GenericRemoteDataSource extends Crypto::GenericRemoteDataSource {
9490
override string getAdditionalDescription() { result = this.toString() }
9591
}
9692

97-
class ConstantDataSource extends Crypto::GenericConstantSourceInstance instanceof Literal {
93+
private class ConstantDataSource extends Crypto::GenericConstantSourceInstance instanceof Literal {
9894
ConstantDataSource() {
9995
// TODO: this is an API specific workaround for JCA, as 'EC' is a constant that may be used
10096
// where typical algorithms are specified, but EC specifically means set up a
@@ -114,14 +110,14 @@ class ConstantDataSource extends Crypto::GenericConstantSourceInstance instanceo
114110
}
115111

116112
/**
117-
* Random number generation, where each instance is modelled as the expression
113+
* An instance of random number generation, modelled as the expression
118114
* tied to an output node (i.e., the result of the source of randomness)
119115
*/
120116
abstract class RandomnessInstance extends Crypto::RandomNumberGenerationInstance {
121117
override DataFlow::Node getOutputNode() { result.asExpr() = this }
122118
}
123119

124-
class SecureRandomnessInstance extends RandomnessInstance {
120+
private class SecureRandomnessInstance extends RandomnessInstance {
125121
RandomDataSource source;
126122

127123
SecureRandomnessInstance() {
@@ -132,7 +128,7 @@ class SecureRandomnessInstance extends RandomnessInstance {
132128
override string getGeneratorName() { result = source.getSourceOfRandomness().getQualifiedName() }
133129
}
134130

135-
class InsecureRandomnessInstance extends RandomnessInstance {
131+
private class InsecureRandomnessInstance extends RandomnessInstance {
136132
RandomDataSource source;
137133

138134
InsecureRandomnessInstance() {
@@ -143,16 +139,18 @@ class InsecureRandomnessInstance extends RandomnessInstance {
143139
}
144140

145141
/**
146-
* Artifact output to node input configuration
142+
* An additional flow step in generic data-flow configurations.
143+
* Where a step is an edge between nodes `n1` and `n2`,
144+
* `this` = `n1` and `getOutput()` = `n2`.
145+
*
146+
* FOR INTERNAL MODELING USE ONLY.
147147
*/
148148
abstract class AdditionalFlowInputStep extends DataFlow::Node {
149149
abstract DataFlow::Node getOutput();
150150

151151
final DataFlow::Node getInput() { result = this }
152152
}
153153

154-
module ArtifactFlow = DataFlow::Global<ArtifactFlowConfig>;
155-
156154
/**
157155
* Generic data source to node input configuration
158156
*/
@@ -214,5 +212,7 @@ module ArtifactFlowConfig implements DataFlow::ConfigSig {
214212

215213
module GenericDataSourceFlow = TaintTracking::Global<GenericDataSourceFlowConfig>;
216214

215+
module ArtifactFlow = DataFlow::Global<ArtifactFlowConfig>;
216+
217217
// Import library-specific modeling
218218
import JCA

java/ql/src/experimental/quantum/InventorySlices/KnownAsymmetricAlgorithm.ql

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,5 @@
1010
import java
1111
import experimental.quantum.Language
1212

13-
from Crypto::AlgorithmNode a
14-
where Crypto::isKnownAsymmetricAlgorithm(a)
13+
from Crypto::AsymmetricAlgorithmNode a
1514
select a, a.getAlgorithmName()

java/ql/src/experimental/quantum/InventorySlices/KnownAsymmetricOperationAlgorithm.ql

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,6 @@
1010
import java
1111
import experimental.quantum.Language
1212

13-
from Crypto::OperationNode op, Crypto::AlgorithmNode a
14-
where a = op.getAKnownAlgorithm() and Crypto::isKnownAsymmetricAlgorithm(a)
13+
from Crypto::OperationNode op, Crypto::AsymmetricAlgorithmNode a
14+
where a = op.getAKnownAlgorithm()
1515
select op, a.getAlgorithmName()

java/ql/src/experimental/quantum/InventorySlices/LikelyCryptoAPIFunction.ql

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
/**
22
* @name Likely crypto API function
3-
* @description Detects functions that take in crypto configuration parameters but calls are not detected in source.
3+
* @description Outputs functions that take in crypto configuration parameters but calls are not detected in source.
44
* @id java/quantum/slices/likely-crypto-api-function
55
* @kind problem
66
* @severity info

shared/quantum/codeql/quantum/experimental/Model.qll

Lines changed: 63 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
*/
44

55
import codeql.util.Location
6-
import codeql.util.Either
76

87
signature module InputSig<LocationSig Location> {
98
class LocatableElement {
@@ -36,10 +35,20 @@ module CryptographyBase<LocationSig Location, InputSig<Location> Input> {
3635

3736
final class DataFlowNode = Input::DataFlowNode;
3837

38+
/**
39+
* A `ConsumerInputDataFlowNode` is a `DataFlowNode` that represents a consumer of data.
40+
*
41+
* This class is equivalent to `DataFlowNode` but facilitates binding to a `ConsumerElement`.
42+
*/
3943
class ConsumerInputDataFlowNode extends DataFlowNode {
4044
ConsumerElement getConsumer() { result.getInputNode() = this }
4145
}
4246

47+
/**
48+
* An `ArtifactOutputDataFlowNode` is a `DataFlowNode` that represents the source of a created artifact.
49+
*
50+
* This class is equivalent to `DataFlowNode` but facilitates binding to an `OutputArtifactInstance`.
51+
*/
4352
class ArtifactOutputDataFlowNode extends DataFlowNode {
4453
OutputArtifactInstance getArtifact() { result.getOutputNode() = this }
4554
}
@@ -51,19 +60,17 @@ module CryptographyBase<LocationSig Location, InputSig<Location> Input> {
5160
bindingset[root]
5261
private string getPropertyAsGraphString(NodeBase node, string key, Location root) {
5362
result =
54-
strictconcat(any(string value, Location location, string parsed |
55-
node.properties(key, value, location) and
56-
(
57-
if location = root or location instanceof UnknownLocation
58-
then parsed = value
59-
else
60-
parsed =
61-
"(" + value + "," + Input::locationToFileBaseNameAndLineNumberString(location) +
62-
")"
63-
)
64-
|
65-
parsed
66-
), ","
63+
strictconcat(string value, Location location, string parsed |
64+
node.properties(key, value, location) and
65+
(
66+
if location = root or location instanceof UnknownLocation
67+
then parsed = value
68+
else
69+
parsed =
70+
"(" + value + "," + Input::locationToFileBaseNameAndLineNumberString(location) + ")"
71+
)
72+
|
73+
parsed, ","
6774
)
6875
}
6976

@@ -154,7 +161,7 @@ module CryptographyBase<LocationSig Location, InputSig<Location> Input> {
154161
* CROSS PRODUCT WARNING: Modeling any *other* element that is a `FlowAwareElement` to the same
155162
* instance in the database will result in every `FlowAwareElement` sharing the output flow.
156163
*/
157-
abstract class KnownElement extends LocatableElement {
164+
abstract private class KnownElement extends LocatableElement {
158165
final ConsumerElement getAConsumer() { result.getAKnownSource() = this }
159166
}
160167

@@ -297,6 +304,23 @@ module CryptographyBase<LocationSig Location, InputSig<Location> Input> {
297304
final override ConsumerInputDataFlowNode getInputNode() { result = input }
298305
}
299306

307+
/**
308+
* An `AlgorithmValueConsumer` (_AVC_) is an element that consumes a value specifying an algorithm.
309+
*
310+
* Example 1:
311+
* `arg0` of `set_algorithm` (`x`) is the AVC for the `ctx.encrypt()` operation.
312+
* ```cpp
313+
* x = "RSA";
314+
* ctx.set_algorithm(x);
315+
* ctx.encrypt();
316+
* ```
317+
*
318+
* Example 2:
319+
* `encrypt_with_rsa` is concurrently an an operation, an AVC, and an algorithm.
320+
* ```cpp
321+
* `encrypt_with_rsa();`
322+
* ```
323+
*/
300324
abstract class AlgorithmValueConsumer extends ConsumerElement {
301325
/**
302326
* DO NOT USE.
@@ -324,8 +348,8 @@ module CryptographyBase<LocationSig Location, InputSig<Location> Input> {
324348
* to the artifact it receives, thereby becoming the definitive contextual source for that artifact.
325349
*
326350
* Architectural Implications:
327-
* * By directly coupling a consumer with the node that receives an artifact,
328-
* the data flow is fully transparent with the consumer itself serving only as a transparent node.
351+
* * By directly coupling a consumer with the node that receives an artifact, no modeling considerations have to be made
352+
* to provide an interface for identifying the source via the consumer data-flow mechanisms.
329353
* * An artifact's properties (such as being a nonce) are not necessarily inherent; they are determined by the context in which the artifact is consumed.
330354
* The consumer node is therefore essential in defining these properties for inputs.
331355
* * This approach reduces ambiguity by avoiding separate notions of "artifact source" and "consumer", as the node itself encapsulates both roles.
@@ -347,7 +371,7 @@ module CryptographyBase<LocationSig Location, InputSig<Location> Input> {
347371
* A `NonceArtifactConsumer` is always the `NonceArtifactInstance` itself, since data only becomes (i.e., is determined to be)
348372
* a `NonceArtifactInstance` when it is consumed in a context that expects a nonce (e.g., an argument expecting nonce data).
349373
*
350-
* In this case, the artifact (nonce) is fully defined by the context in which it is consumed, and the consumer embodies
374+
* In this case, the artifact (nonce) is fully defined by the context in which it is consumed, and the consumer embodies
351375
* that identity without the need for additional differentiation. Without the context a consumer provides, that data could
352376
* otherwise be any other type of artifact or even simply random data.
353377
*
@@ -604,7 +628,6 @@ module CryptographyBase<LocationSig Location, InputSig<Location> Input> {
604628
type = TSymmetricCipher(SEED()) and size = 128
605629
}
606630

607-
bindingset[type]
608631
predicate symmetric_cipher_to_name_and_structure(
609632
TSymmetricCipherType type, string name, CipherStructureType s
610633
) {
@@ -651,7 +674,6 @@ module CryptographyBase<LocationSig Location, InputSig<Location> Input> {
651674
s = UnknownCipherStructureType()
652675
}
653676

654-
bindingset[type]
655677
predicate type_to_name(Algorithm type, string name) {
656678
// Symmetric cipher algorithm
657679
symmetric_cipher_to_name_and_structure(type.(SymmetricCipherAlgorithm).getType(), name, _)
@@ -1551,6 +1573,20 @@ module CryptographyBase<LocationSig Location, InputSig<Location> Input> {
15511573
string toString() { result = super.getAlgorithmName() }
15521574
}
15531575

1576+
/**
1577+
* The subset of algorithm nodes that are known asymmetric algorithm.
1578+
*
1579+
* Note: This is not an independent top-level node type.
1580+
*/
1581+
class AsymmetricAlgorithmNode extends TKeyCreationCandidateAlgorithm instanceof AlgorithmNode {
1582+
AsymmetricAlgorithmNode() {
1583+
this instanceof EllipticCurveNode or
1584+
this.(KeyOperationAlgorithmNode).isAsymmetric()
1585+
}
1586+
1587+
string toString() { result = super.getAlgorithmName() }
1588+
}
1589+
15541590
/**
15551591
* A cryptographic key, such as a symmetric key or asymmetric key pair.
15561592
*/
@@ -1709,7 +1745,6 @@ module CryptographyBase<LocationSig Location, InputSig<Location> Input> {
17091745

17101746
TMACType getMACType() { result = instance.asAlg().getMACType() }
17111747

1712-
bindingset[type]
17131748
final private predicate macToNameMapping(TMACType type, string name) {
17141749
type instanceof THMAC and
17151750
name = "HMAC"
@@ -2102,7 +2137,6 @@ module CryptographyBase<LocationSig Location, InputSig<Location> Input> {
21022137
*/
21032138
TBlockCipherModeOfOperationType getModeType() { result = instance.getModeType() }
21042139

2105-
bindingset[type]
21062140
final private predicate modeToNameMapping(TBlockCipherModeOfOperationType type, string name) {
21072141
type = ECB() and name = "ECB"
21082142
or
@@ -2148,7 +2182,6 @@ module CryptographyBase<LocationSig Location, InputSig<Location> Input> {
21482182

21492183
TPaddingType getPaddingType() { result = instance.getPaddingType() }
21502184

2151-
bindingset[type]
21522185
final private predicate paddingToNameMapping(TPaddingType type, string name) {
21532186
type = ANSI_X9_23() and name = "ANSI_X9_23"
21542187
or
@@ -2454,18 +2487,18 @@ module CryptographyBase<LocationSig Location, InputSig<Location> Input> {
24542487
// ALL BRAINPOOL CURVES
24552488
keySize in [160, 192, 224, 256, 320, 384, 512] and
24562489
(
2457-
curveName = "BRAINPOOLP" + keySize.toString() + "R1"
2490+
curveName = "BRAINPOOLP" + keySize + "R1"
24582491
or
2459-
curveName = "BRAINPOOLP" + keySize.toString() + "T1"
2492+
curveName = "BRAINPOOLP" + keySize + "T1"
24602493
)
24612494
}
24622495

24632496
private predicate isSecCurve(string curveName, int keySize) {
24642497
// ALL SEC CURVES
24652498
keySize in [112, 113, 128, 131, 160, 163, 192, 193, 224, 233, 239, 256, 283, 384, 409, 521, 571] and
24662499
exists(string suff | suff in ["R1", "R2", "K1"] |
2467-
curveName = "SECT" + keySize.toString() + suff or
2468-
curveName = "SECP" + keySize.toString() + suff
2500+
curveName = "SECT" + keySize + suff or
2501+
curveName = "SECP" + keySize + suff
24692502
)
24702503
}
24712504

@@ -2475,22 +2508,20 @@ module CryptographyBase<LocationSig Location, InputSig<Location> Input> {
24752508
exists(string pre, string suff |
24762509
pre in ["PNB", "ONB", "TNB"] and suff in ["V1", "V2", "V3", "V4", "V5", "W1", "R1"]
24772510
|
2478-
curveName = "C2" + pre + keySize.toString() + suff
2511+
curveName = "C2" + pre + keySize + suff
24792512
)
24802513
}
24812514

24822515
private predicate isPrimeCurve(string curveName, int keySize) {
24832516
// ALL PRIME CURVES
24842517
keySize in [192, 239, 256] and
2485-
exists(string suff | suff in ["V1", "V2", "V3"] |
2486-
curveName = "PRIME" + keySize.toString() + suff
2487-
)
2518+
exists(string suff | suff in ["V1", "V2", "V3"] | curveName = "PRIME" + keySize + suff)
24882519
}
24892520

24902521
private predicate isNumsCurve(string curveName, int keySize) {
24912522
// ALL NUMS CURVES
24922523
keySize in [256, 384, 512] and
2493-
exists(string suff | suff = "T1" | curveName = "NUMSP" + keySize.toString() + suff)
2524+
exists(string suff | suff = "T1" | curveName = "NUMSP" + keySize + suff)
24942525
}
24952526

24962527
/**
@@ -2587,10 +2618,4 @@ module CryptographyBase<LocationSig Location, InputSig<Location> Input> {
25872618
location = this.getLocation()
25882619
}
25892620
}
2590-
2591-
predicate isKnownAsymmetricAlgorithm(AlgorithmNode node) {
2592-
node instanceof EllipticCurveNode
2593-
or
2594-
node instanceof KeyOperationAlgorithmNode and node.(KeyOperationAlgorithmNode).isAsymmetric()
2595-
}
25962621
}

0 commit comments

Comments
 (0)