mirror of
https://github.com/github/codeql.git
synced 2026-04-26 17:25:19 +02:00
Add modelling for JCA key gen cipher algorithm
This commit is contained in:
@@ -2,7 +2,6 @@ import java
|
||||
import semmle.code.java.dataflow.DataFlow
|
||||
import semmle.code.java.dataflow.TaintTracking
|
||||
import semmle.code.java.controlflow.Dominance
|
||||
import codeql.util.Option
|
||||
|
||||
module JCAModel {
|
||||
import Language
|
||||
@@ -354,9 +353,11 @@ module JCAModel {
|
||||
else result instanceof KeyOpAlg::TUnknownKeyOperationAlgorithmType
|
||||
}
|
||||
|
||||
override string getKeySize() {
|
||||
override string getKeySizeFixed() {
|
||||
none() // TODO: implement to handle variants such as AES-128
|
||||
}
|
||||
|
||||
override Crypto::ConsumerInputDataFlowNode getKeySizeConsumer() { none() }
|
||||
}
|
||||
|
||||
bindingset[input]
|
||||
@@ -394,8 +395,6 @@ module JCAModel {
|
||||
override Crypto::HashAlgorithmInstance getOAEPEncodingHashAlgorithm() { result = this }
|
||||
|
||||
override Crypto::HashAlgorithmInstance getMGF1HashAlgorithm() { none() } // TODO
|
||||
|
||||
override string getKeySize() { none() }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -446,8 +445,6 @@ module JCAModel {
|
||||
predicate isIntermediate();
|
||||
}
|
||||
|
||||
module MethodCallOption = Option<MethodCall>;
|
||||
|
||||
/**
|
||||
* An generic analysis module for analyzing the `getInstance` to `initialize` to `doOperation` pattern in the JCA.
|
||||
*
|
||||
@@ -568,6 +565,14 @@ module JCAModel {
|
||||
GetInstanceToInitToUseFlow::flowPath(src, sink)
|
||||
}
|
||||
|
||||
GetInstance getInstantiationFromInit(
|
||||
Init init, GetInstanceToInitToUseFlow::PathNode src, GetInstanceToInitToUseFlow::PathNode sink
|
||||
) {
|
||||
src.getNode().asExpr() = result and
|
||||
sink.getNode().asExpr() = init.(MethodCall).getQualifier() and
|
||||
GetInstanceToInitToUseFlow::flowPath(src, sink)
|
||||
}
|
||||
|
||||
Init getInitFromUse(
|
||||
Use use, GetInstanceToInitToUseFlow::PathNode src, GetInstanceToInitToUseFlow::PathNode sink
|
||||
) {
|
||||
@@ -829,6 +834,9 @@ module JCAModel {
|
||||
}
|
||||
}
|
||||
|
||||
module MessageDigestFlowAnalysisImpl =
|
||||
GetInstanceInitUseFlowAnalysis<MessageDigestGetInstanceCall, DUMMY_UNUSED_METHODCALL, DigestCall>;
|
||||
|
||||
class MessageDigestGetInstanceAlgorithmValueConsumer extends HashAlgorithmValueConsumer {
|
||||
MessageDigestGetInstanceCall call;
|
||||
|
||||
@@ -849,17 +857,18 @@ module JCAModel {
|
||||
}
|
||||
|
||||
Expr getAlgorithmArg() { result = this.getArgument(0) }
|
||||
|
||||
DigestHashOperation getDigestCall() {
|
||||
DigestGetInstanceToDigestFlow::flow(DataFlow::exprNode(this),
|
||||
DataFlow::exprNode(result.(DigestCall).getQualifier()))
|
||||
}
|
||||
}
|
||||
|
||||
class DigestCall extends MethodCall {
|
||||
DigestCall() { this.getCallee().hasQualifiedName("java.security", "MessageDigest", "digest") }
|
||||
DigestCall() {
|
||||
this.getCallee().hasQualifiedName("java.security", "MessageDigest", ["update", "digest"])
|
||||
}
|
||||
|
||||
Expr getDigestArtifactOutput() { result = this }
|
||||
|
||||
Expr getInputArg() { result = this.getArgument(0) }
|
||||
|
||||
predicate isIntermediate() { this.getMethod().getName() = "update" }
|
||||
}
|
||||
|
||||
// flow config from MessageDigest.getInstance to MessageDigest.digest
|
||||
@@ -873,23 +882,22 @@ module JCAModel {
|
||||
|
||||
module DigestGetInstanceToDigestFlow = DataFlow::Global<DigestGetInstanceToDigestConfig>;
|
||||
|
||||
class DigestArtifact extends Crypto::DigestArtifactInstance {
|
||||
DigestArtifact() { this = any(DigestCall call).getDigestArtifactOutput() }
|
||||
|
||||
override DataFlow::Node getOutputNode() { result.asExpr() = this }
|
||||
}
|
||||
|
||||
class DigestHashOperation extends Crypto::HashOperationInstance instanceof DigestCall {
|
||||
override Crypto::DigestArtifactInstance getDigestArtifact() {
|
||||
result = this.(DigestCall).getDigestArtifactOutput()
|
||||
DigestHashOperation() { not super.isIntermediate() }
|
||||
|
||||
override Crypto::ArtifactOutputDataFlowNode getOutputArtifact() {
|
||||
result.asExpr() = super.getDigestArtifactOutput()
|
||||
}
|
||||
|
||||
override Crypto::AlgorithmValueConsumer getAnAlgorithmValueConsumer() {
|
||||
exists(MessageDigestGetInstanceCall getInstanceCall |
|
||||
getInstanceCall.getDigestCall() = this and
|
||||
getInstanceCall =
|
||||
result.(MessageDigestGetInstanceAlgorithmValueConsumer).getInstantiationCall()
|
||||
)
|
||||
MessageDigestFlowAnalysisImpl::getInstantiationFromUse(this, _, _) =
|
||||
result.(MessageDigestGetInstanceAlgorithmValueConsumer).getInstantiationCall()
|
||||
}
|
||||
|
||||
override Crypto::ConsumerInputDataFlowNode getInputConsumer() {
|
||||
result.asExpr() = super.getInputArg() or
|
||||
result.asExpr() =
|
||||
MessageDigestFlowAnalysisImpl::getAnIntermediateUseFromFinalUse(this, _, _).getInputArg()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -997,6 +1005,7 @@ module JCAModel {
|
||||
or
|
||||
// However, for general elliptic curves, getInstance("EC") is used
|
||||
// and java.security.spec.ECGenParameterSpec("<CURVE NAME>") is what sets the specific curve.
|
||||
// If init is not specified, the default (P-)
|
||||
// The result of ECGenParameterSpec is passed to KeyPairGenerator.initialize
|
||||
// If the curve is not specified, the default is used.
|
||||
// We would trace the use of this inside a KeyPairGenerator.initialize
|
||||
@@ -1096,6 +1105,30 @@ module JCAModel {
|
||||
override string getKeySizeFixed() { none() }
|
||||
}
|
||||
|
||||
class KeyGeneratorCipherAlgorithm extends CipherStringLiteralAlgorithmInstance {
|
||||
KeyGeneratorCipherAlgorithm() { consumer instanceof KeyGenerationAlgorithmValueConsumer }
|
||||
|
||||
override Crypto::ConsumerInputDataFlowNode getKeySizeConsumer() {
|
||||
exists(KeyGeneratorGetInstanceCall getInstance, KeyGeneratorInitCall init |
|
||||
getInstance =
|
||||
this.getConsumer().(KeyGenerationAlgorithmValueConsumer).getInstantiationCall() and
|
||||
getInstance = KeyGeneratorFlowAnalysisImpl::getInstantiationFromInit(init, _, _) and
|
||||
init.getKeySizeArg() = result.asExpr()
|
||||
)
|
||||
}
|
||||
|
||||
predicate isOnlyConsumedByKeyGen() {
|
||||
forall(Crypto::AlgorithmValueConsumer c |
|
||||
c = this.getConsumer() and
|
||||
c instanceof KeyGenerationAlgorithmValueConsumer
|
||||
)
|
||||
}
|
||||
|
||||
override predicate shouldHaveModeOfOperation() { this.isOnlyConsumedByKeyGen() }
|
||||
|
||||
override predicate shouldHavePaddingScheme() { this.isOnlyConsumedByKeyGen() }
|
||||
}
|
||||
|
||||
/*
|
||||
* Key Derivation Functions (KDFs)
|
||||
*/
|
||||
|
||||
@@ -38,7 +38,7 @@ module CryptoInput implements InputSig<Language::Location> {
|
||||
predicate artifactOutputFlowsToGenericInput(
|
||||
DataFlow::Node artifactOutput, DataFlow::Node otherInput
|
||||
) {
|
||||
ArtifactUniversalFlow::flow(artifactOutput, otherInput)
|
||||
ArtifactFlow::flow(artifactOutput, otherInput)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -60,7 +60,7 @@ class GenericUnreferencedParameterSource extends Crypto::GenericUnreferencedPara
|
||||
}
|
||||
|
||||
override predicate flowsTo(Crypto::FlowAwareElement other) {
|
||||
GenericDataSourceUniversalFlow::flow(this.getOutputNode(), other.getInputNode())
|
||||
GenericDataSourceFlow::flow(this.getOutputNode(), other.getInputNode())
|
||||
}
|
||||
|
||||
override DataFlow::Node getOutputNode() { result.asParameter() = this }
|
||||
@@ -76,7 +76,7 @@ class GenericLocalDataSource extends Crypto::GenericLocalDataSource {
|
||||
override DataFlow::Node getOutputNode() { result.asExpr() = this }
|
||||
|
||||
override predicate flowsTo(Crypto::FlowAwareElement other) {
|
||||
GenericDataSourceUniversalFlow::flow(this.getOutputNode(), other.getInputNode())
|
||||
GenericDataSourceFlow::flow(this.getOutputNode(), other.getInputNode())
|
||||
}
|
||||
|
||||
override string getAdditionalDescription() { result = this.toString() }
|
||||
@@ -88,7 +88,7 @@ class GenericRemoteDataSource extends Crypto::GenericRemoteDataSource {
|
||||
override DataFlow::Node getOutputNode() { result.asExpr() = this }
|
||||
|
||||
override predicate flowsTo(Crypto::FlowAwareElement other) {
|
||||
GenericDataSourceUniversalFlow::flow(this.getOutputNode(), other.getInputNode())
|
||||
GenericDataSourceFlow::flow(this.getOutputNode(), other.getInputNode())
|
||||
}
|
||||
|
||||
override string getAdditionalDescription() { result = this.toString() }
|
||||
@@ -107,7 +107,7 @@ class ConstantDataSource extends Crypto::GenericConstantSourceInstance instanceo
|
||||
|
||||
override predicate flowsTo(Crypto::FlowAwareElement other) {
|
||||
// TODO: separate config to avoid blowing up data-flow analysis
|
||||
GenericDataSourceUniversalFlow::flow(this.getOutputNode(), other.getInputNode())
|
||||
GenericDataSourceFlow::flow(this.getOutputNode(), other.getInputNode())
|
||||
}
|
||||
|
||||
override string getAdditionalDescription() { result = this.toString() }
|
||||
@@ -122,15 +122,24 @@ abstract class RandomnessInstance extends Crypto::RandomNumberGenerationInstance
|
||||
}
|
||||
|
||||
class SecureRandomnessInstance extends RandomnessInstance {
|
||||
RandomDataSource source;
|
||||
|
||||
SecureRandomnessInstance() {
|
||||
exists(RandomDataSource s | this = s.getOutput() |
|
||||
s.getSourceOfRandomness() instanceof SecureRandomNumberGenerator
|
||||
)
|
||||
this = source.getOutput() and
|
||||
source.getSourceOfRandomness() instanceof SecureRandomNumberGenerator
|
||||
}
|
||||
|
||||
override string getGeneratorName() { result = source.getSourceOfRandomness().getQualifiedName() }
|
||||
}
|
||||
|
||||
class InsecureRandomnessInstance extends RandomnessInstance {
|
||||
InsecureRandomnessInstance() { exists(InsecureRandomnessSource node | this = node.asExpr()) }
|
||||
RandomDataSource source;
|
||||
|
||||
InsecureRandomnessInstance() {
|
||||
any(InsecureRandomnessSource src).asExpr() = this and source.getOutput() = this
|
||||
}
|
||||
|
||||
override string getGeneratorName() { result = source.getSourceOfRandomness().getQualifiedName() }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -142,12 +151,12 @@ abstract class AdditionalFlowInputStep extends DataFlow::Node {
|
||||
final DataFlow::Node getInput() { result = this }
|
||||
}
|
||||
|
||||
module ArtifactUniversalFlow = DataFlow::Global<ArtifactUniversalFlowConfig>;
|
||||
module ArtifactFlow = DataFlow::Global<ArtifactFlowConfig>;
|
||||
|
||||
/**
|
||||
* Generic data source to node input configuration
|
||||
*/
|
||||
module GenericDataSourceUniversalFlowConfig implements DataFlow::ConfigSig {
|
||||
module GenericDataSourceFlowConfig implements DataFlow::ConfigSig {
|
||||
predicate isSource(DataFlow::Node source) {
|
||||
source = any(Crypto::GenericSourceInstance i).getOutputNode()
|
||||
}
|
||||
@@ -175,7 +184,7 @@ module GenericDataSourceUniversalFlowConfig implements DataFlow::ConfigSig {
|
||||
}
|
||||
}
|
||||
|
||||
module ArtifactUniversalFlowConfig implements DataFlow::ConfigSig {
|
||||
module ArtifactFlowConfig implements DataFlow::ConfigSig {
|
||||
predicate isSource(DataFlow::Node source) {
|
||||
source = any(Crypto::ArtifactInstance artifact).getOutputNode()
|
||||
}
|
||||
@@ -203,7 +212,7 @@ module ArtifactUniversalFlowConfig implements DataFlow::ConfigSig {
|
||||
}
|
||||
}
|
||||
|
||||
module GenericDataSourceUniversalFlow = TaintTracking::Global<GenericDataSourceUniversalFlowConfig>;
|
||||
module GenericDataSourceFlow = TaintTracking::Global<GenericDataSourceFlowConfig>;
|
||||
|
||||
// Import library-specific modeling
|
||||
import JCA
|
||||
|
||||
20
java/ql/src/experimental/Quantum/InsecureNonceSource.ql
Normal file
20
java/ql/src/experimental/Quantum/InsecureNonceSource.ql
Normal file
@@ -0,0 +1,20 @@
|
||||
/**
|
||||
* @name Insecure nonce at a cipher operation
|
||||
* @id java/insecure-nonce
|
||||
* @kind problem
|
||||
* @problem.severity error
|
||||
* @precision high
|
||||
* @description A nonce is generated from a source that is not secure. This can lead to
|
||||
* vulnerabilities such as replay attacks or key recovery.
|
||||
*/
|
||||
|
||||
import experimental.Quantum.Language
|
||||
|
||||
predicate isInsecureNonceSource(Crypto::NonceArtifactNode n, Crypto::NodeBase src) {
|
||||
src = n.getSourceNode() and
|
||||
not src.asElement() instanceof SecureRandomnessInstance
|
||||
}
|
||||
|
||||
from Crypto::KeyOperationNode op, Crypto::NodeBase src
|
||||
where isInsecureNonceSource(op.getANonce(), src)
|
||||
select op, "Operation uses insecure nonce source $@", src, src.toString()
|
||||
16
java/ql/src/experimental/Quantum/TestAESGCMNonce.ql
Normal file
16
java/ql/src/experimental/Quantum/TestAESGCMNonce.ql
Normal file
@@ -0,0 +1,16 @@
|
||||
/**
|
||||
* @name "PQC Test"
|
||||
*/
|
||||
|
||||
import experimental.Quantum.Language
|
||||
|
||||
class AESGCMAlgorithmNode extends Crypto::KeyOperationAlgorithmNode {
|
||||
AESGCMAlgorithmNode() {
|
||||
this.getAlgorithmType() = Crypto::KeyOpAlg::TSymmetricCipher(Crypto::KeyOpAlg::AES()) and
|
||||
this.getModeOfOperation().getModeType() = Crypto::GCM()
|
||||
}
|
||||
}
|
||||
|
||||
from Crypto::KeyOperationNode op, Crypto::NonceArtifactNode nonce
|
||||
where op.getAKnownAlgorithm() instanceof AESGCMAlgorithmNode and nonce = op.getANonce()
|
||||
select op, nonce.getSourceNode()
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* @name "PQC Test"
|
||||
* @name "Key operation slice table demo query"
|
||||
*/
|
||||
|
||||
import experimental.Quantum.Language
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
/**
|
||||
* @name TestHashOperations
|
||||
* @name "Hash operation slice table demo query"
|
||||
*/
|
||||
|
||||
import experimental.Quantum.Language
|
||||
|
||||
from Crypto::HashOperationNode op, Crypto::HashAlgorithmNode alg
|
||||
where alg = op.getAKnownHashAlgorithm()
|
||||
where alg = op.getAKnownAlgorithm()
|
||||
select op, op.getDigest(), alg, alg.getRawAlgorithmName()
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
import os
|
||||
import re
|
||||
import sys
|
||||
import argparse
|
||||
import subprocess
|
||||
@@ -86,6 +87,7 @@ def main():
|
||||
parser.add_argument("-c", "--codeql", required=True, help="Path to CodeQL CLI executable.")
|
||||
parser.add_argument("-d", "--database", required=True, help="Path to the CodeQL database.")
|
||||
parser.add_argument("-q", "--query", required=True, help="Path to the .ql query file.")
|
||||
parser.add_argument("--queryid", required=True, help="Query ID for the analysis.")
|
||||
parser.add_argument("-o", "--output", required=True, help="Output directory for analysis results.")
|
||||
|
||||
args = parser.parse_args()
|
||||
@@ -94,7 +96,13 @@ def main():
|
||||
run_codeql_analysis(args.codeql, args.database, args.query, args.output)
|
||||
|
||||
# Locate DGML file
|
||||
dgml_file = os.path.join(args.output, "java", "print-cbom-graph.dgml")
|
||||
ALLOWED_QUERY_ID = re.compile(r'^[a-zA-Z0-9_\-]+$')
|
||||
|
||||
if not ALLOWED_QUERY_ID.match(args.queryid):
|
||||
print("Invalid query_id provided: '%s'. Allowed characters: letters, digits, '_', and '-'.", args.queryid)
|
||||
sys.exit(1)
|
||||
|
||||
dgml_file = os.path.join(args.output, "java", '{}.dgml'.format(args.queryid))
|
||||
dot_file = dgml_file.replace(".dgml", ".dot")
|
||||
|
||||
if os.path.exists(dgml_file):
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
*/
|
||||
|
||||
import codeql.util.Location
|
||||
import codeql.util.Option
|
||||
import codeql.util.Either
|
||||
|
||||
signature module InputSig<LocationSig Location> {
|
||||
@@ -379,6 +378,8 @@ module CryptographyBase<LocationSig Location, InputSig<Location> Input> {
|
||||
exists(KeyDerivationOperationInstance op | inputNode = op.getInputConsumer())
|
||||
or
|
||||
exists(MACOperationInstance op | inputNode = op.getMessageConsumer())
|
||||
or
|
||||
exists(HashOperationInstance op | inputNode = op.getInputConsumer())
|
||||
) and
|
||||
this = Input::dfn_to_element(inputNode)
|
||||
}
|
||||
@@ -410,16 +411,11 @@ module CryptographyBase<LocationSig Location, InputSig<Location> Input> {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* An artifact representing a hash function's digest output.
|
||||
*/
|
||||
abstract class DigestArtifactInstance extends OutputArtifactInstance { }
|
||||
|
||||
/**
|
||||
* An artifact representing a random number generator's output.
|
||||
*/
|
||||
abstract class RandomNumberGenerationInstance extends OutputArtifactInstance {
|
||||
// TODO: input seed?
|
||||
abstract string getGeneratorName();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -438,6 +434,17 @@ module CryptographyBase<LocationSig Location, InputSig<Location> Input> {
|
||||
override DataFlowNode getOutputNode() { result = creator.getOutputArtifact() }
|
||||
}
|
||||
|
||||
/**
|
||||
* An artifact representing the message digest output of a hash operation.
|
||||
*/
|
||||
final class HashOutputArtifactInstance extends OutputArtifactInstance {
|
||||
HashOperationInstance creator;
|
||||
|
||||
HashOutputArtifactInstance() { Input::dfn_to_element(creator.getOutputArtifact()) = this }
|
||||
|
||||
override DataFlowNode getOutputNode() { result = creator.getOutputArtifact() }
|
||||
}
|
||||
|
||||
/**
|
||||
* An artifact representing the shared secret generated by key agreement operations.
|
||||
*/
|
||||
@@ -489,8 +496,14 @@ module CryptographyBase<LocationSig Location, InputSig<Location> Input> {
|
||||
// TODO: key type hint? e.g. hint: private || public
|
||||
KeyArtifactConsumer() {
|
||||
(
|
||||
exists(KeyOperationInstance op | inputNode = op.getKeyConsumer()) or
|
||||
exists(KeyOperationInstance op | inputNode = op.getKeyConsumer())
|
||||
or
|
||||
exists(MACOperationInstance op | inputNode = op.getKeyConsumer())
|
||||
or
|
||||
exists(KeyAgreementSecretGenerationOperationInstance op |
|
||||
inputNode = op.getServerKeyConsumer() or
|
||||
inputNode = op.getPeerKeyConsumer()
|
||||
)
|
||||
) and
|
||||
this = Input::dfn_to_element(inputNode)
|
||||
}
|
||||
@@ -770,7 +783,22 @@ module CryptographyBase<LocationSig Location, InputSig<Location> Input> {
|
||||
*
|
||||
* If the algorithm accepts a range of key sizes without a particular one specified, this predicate should be implemented as `none()`.
|
||||
*/
|
||||
abstract string getKeySize();
|
||||
abstract string getKeySizeFixed();
|
||||
|
||||
/**
|
||||
* Gets a consumer for the key size in bits specified for this algorithm variant.
|
||||
*/
|
||||
abstract ConsumerInputDataFlowNode getKeySizeConsumer();
|
||||
|
||||
/**
|
||||
* Holds if this algorithm is expected to have a mode specified.
|
||||
*/
|
||||
predicate shouldHaveModeOfOperation() { any() }
|
||||
|
||||
/**
|
||||
* Holds if this algorithm is expected to have a padding scheme specified.
|
||||
*/
|
||||
predicate shouldHavePaddingScheme() { any() }
|
||||
}
|
||||
|
||||
newtype TBlockCipherModeOfOperationType =
|
||||
@@ -904,7 +932,9 @@ module CryptographyBase<LocationSig Location, InputSig<Location> Input> {
|
||||
}
|
||||
|
||||
abstract class HashOperationInstance extends OperationInstance {
|
||||
abstract DigestArtifactInstance getDigestArtifact();
|
||||
abstract ArtifactOutputDataFlowNode getOutputArtifact();
|
||||
|
||||
abstract ConsumerInputDataFlowNode getInputConsumer();
|
||||
}
|
||||
|
||||
abstract class HashAlgorithmInstance extends AlgorithmInstance {
|
||||
@@ -1151,7 +1181,7 @@ module CryptographyBase<LocationSig Location, InputSig<Location> Input> {
|
||||
|
||||
private newtype TNode =
|
||||
// Output artifacts (data that is not an operation or algorithm, e.g., a key)
|
||||
TDigest(DigestArtifactInstance e) or
|
||||
TDigest(HashOutputArtifactInstance e) or
|
||||
TKey(KeyArtifactInstance e) or
|
||||
TSharedSecret(KeyAgreementSharedSecretOutputArtifactInstance e) or
|
||||
// Input artifacts (synthetic nodes, used to differentiate input as entities)
|
||||
@@ -1442,6 +1472,15 @@ module CryptographyBase<LocationSig Location, InputSig<Location> Input> {
|
||||
override LocatableElement asElement() { result = instance }
|
||||
|
||||
override string getSourceNodeRelationship() { none() } // TODO: seed?
|
||||
|
||||
override predicate properties(string key, string value, Location location) {
|
||||
super.properties(key, value, location)
|
||||
or
|
||||
// [ONLY_KNOWN]
|
||||
key = "Description" and
|
||||
value = instance.getGeneratorName() and
|
||||
location = this.getLocation()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1518,7 +1557,7 @@ module CryptographyBase<LocationSig Location, InputSig<Location> Input> {
|
||||
* A digest artifact produced by a hash operation.
|
||||
*/
|
||||
final class DigestArtifactNode extends ArtifactNode, TDigest {
|
||||
DigestArtifactInstance instance;
|
||||
HashOutputArtifactInstance instance;
|
||||
|
||||
DigestArtifactNode() { this = TDigest(instance) }
|
||||
|
||||
@@ -1664,12 +1703,28 @@ module CryptographyBase<LocationSig Location, InputSig<Location> Input> {
|
||||
result.asElement() = instance.getOutputArtifact().getArtifact()
|
||||
}
|
||||
|
||||
KeyArtifactNode getServerKey() {
|
||||
result.asElement() = instance.getServerKeyConsumer().getConsumer()
|
||||
}
|
||||
|
||||
KeyArtifactNode getPeerKey() {
|
||||
result.asElement() = instance.getPeerKeyConsumer().getConsumer()
|
||||
}
|
||||
|
||||
override NodeBase getChild(string key) {
|
||||
result = super.getChild(key)
|
||||
or
|
||||
// [ALWAYS_KNOWN]
|
||||
key = "Output" and
|
||||
result = this.getOutput()
|
||||
or
|
||||
// [KNOWN_OR_UNKOWN]
|
||||
key = "ServerKey" and
|
||||
if exists(this.getServerKey()) then result = this.getServerKey() else result = this
|
||||
or
|
||||
// [KNOWN_OR_UNKOWN]
|
||||
key = "PeerKey" and
|
||||
if exists(this.getPeerKey()) then result = this.getPeerKey() else result = this
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2115,7 +2170,14 @@ module CryptographyBase<LocationSig Location, InputSig<Location> Input> {
|
||||
/**
|
||||
* Gets the key size variant of this algorithm in bits, e.g., 128 for "AES-128".
|
||||
*/
|
||||
string getKeySize() { result = instance.asAlg().getKeySize() } // TODO: key sizes for known algorithms
|
||||
string getKeySizeFixed() { result = instance.asAlg().getKeySizeFixed() } // TODO: key sizes for known algorithms
|
||||
|
||||
/**
|
||||
* Gets the key size generic source node.
|
||||
*/
|
||||
GenericSourceNode getKeySize() {
|
||||
result = instance.asAlg().getKeySizeConsumer().getConsumer().getAGenericSourceNode()
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the type of this key operation algorithm, e.g., "SymmetricEncryption(_)" or ""
|
||||
@@ -2139,17 +2201,23 @@ module CryptographyBase<LocationSig Location, InputSig<Location> Input> {
|
||||
override NodeBase getChild(string edgeName) {
|
||||
result = super.getChild(edgeName)
|
||||
or
|
||||
// [KNOWN_OR_UNKNOWN]
|
||||
// [KNOWN_OR_UNKNOWN] - but only if not suppressed
|
||||
edgeName = "Mode" and
|
||||
if exists(this.getModeOfOperation())
|
||||
then result = this.getModeOfOperation()
|
||||
else result = this
|
||||
(
|
||||
if exists(this.getModeOfOperation())
|
||||
then result = this.getModeOfOperation()
|
||||
else result = this
|
||||
) and
|
||||
instance.asAlg().shouldHaveModeOfOperation()
|
||||
or
|
||||
// [KNOWN_OR_UNKNOWN]
|
||||
// [KNOWN_OR_UNKNOWN] - but only if not suppressed
|
||||
edgeName = "Padding" and
|
||||
if exists(this.getPaddingAlgorithm())
|
||||
then result = this.getPaddingAlgorithm()
|
||||
else result = this
|
||||
(
|
||||
if exists(this.getPaddingAlgorithm())
|
||||
then result = this.getPaddingAlgorithm()
|
||||
else result = this
|
||||
) and
|
||||
instance.asAlg().shouldHavePaddingScheme()
|
||||
}
|
||||
|
||||
override predicate properties(string key, string value, Location location) {
|
||||
@@ -2160,14 +2228,13 @@ module CryptographyBase<LocationSig Location, InputSig<Location> Input> {
|
||||
this.getSymmetricCipherStructure().toString() = value and
|
||||
location = this.getLocation()
|
||||
or
|
||||
// [ONLY_KNOWN]
|
||||
key = "KeySize" and
|
||||
(
|
||||
// [KNOWN_OR_UNKNOWN]
|
||||
key = "KeySize" and
|
||||
if exists(this.getKeySize())
|
||||
then value = this.getKeySize()
|
||||
else (
|
||||
value instanceof UnknownPropertyValue and location instanceof UnknownLocation
|
||||
)
|
||||
value = this.getKeySizeFixed() and
|
||||
location = this.getLocation()
|
||||
or
|
||||
node_as_property(this.getKeySize(), value, location)
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -2191,10 +2258,16 @@ module CryptographyBase<LocationSig Location, InputSig<Location> Input> {
|
||||
node instanceof HashAlgorithmNode
|
||||
}
|
||||
|
||||
MessageArtifactNode getInputArtifact() {
|
||||
result.asElement() = instance.getInputConsumer().getConsumer()
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the output digest node
|
||||
*/
|
||||
DigestArtifactNode getDigest() { result.asElement() = instance.getDigestArtifact() }
|
||||
DigestArtifactNode getDigest() {
|
||||
result.asElement() = instance.getOutputArtifact().getArtifact()
|
||||
}
|
||||
|
||||
override NodeBase getChild(string key) {
|
||||
result = super.getChild(key)
|
||||
@@ -2202,6 +2275,10 @@ module CryptographyBase<LocationSig Location, InputSig<Location> Input> {
|
||||
// [KNOWN_OR_UNKNOWN]
|
||||
key = "Digest" and
|
||||
if exists(this.getDigest()) then result = this.getDigest() else result = this
|
||||
or
|
||||
// [KNOWN_OR_UNKNOWN]
|
||||
key = "Message" and
|
||||
if exists(this.getInputArtifact()) then result = this.getInputArtifact() else result = this
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user